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, int rootNum) {
35 this.sNodeVecs = snodevecs;
36 this.rootNum = rootNum;
37 this.node2Combine = null;
38 this.rootNodes = null;
41 public boolean nextGen() {
42 boolean trial = false;
43 if(this.rootNodes == null) {
44 int num2choose = this.rootNum;
45 this.rootNodes = new Vector<Vector<ScheduleNode>>();
46 this.rootNodes.add(new Vector<ScheduleNode>());
47 Vector<ScheduleNode> toadd = this.sNodeVecs.elementAt(0);
48 for(int i = 0; i < toadd.size(); i++) {
49 // should be only one element: startup object
50 this.rootNodes.elementAt(0).add(toadd.elementAt(i));
54 trial = trial(num2choose, next);
57 if(this.rootNodes.size() == 1) {
60 int next = this.rootNodes.lastElement().elementAt(0).getCid() + 1;
62 while(next == this.sNodeVecs.size()) {
64 num2choose = this.rootNodes.lastElement().size();
65 this.rootNodes.removeElementAt(this.rootNodes.size() - 1);
66 if(this.rootNodes.size() == 1) {
67 // only startup object left, no more choices
70 next = this.rootNodes.lastElement().elementAt(0).getCid() + 1;
73 // reduce one from the last one
74 this.rootNodes.lastElement().removeElementAt(this.rootNodes.lastElement().size() - 1);
75 if(this.rootNodes.lastElement().size() == 0) {
76 this.rootNodes.removeElementAt(this.rootNodes.size() - 1);
79 trial = trial(num2choose, next);
82 // left nodes are all to be combined
83 this.node2Combine = new Vector<Vector<ScheduleNode>>();
86 for(int i = 1; i < this.rootNodes.size(); i++) {
87 int tmp = this.rootNodes.elementAt(i).elementAt(0).getCid();
89 Vector<ScheduleNode> toadd = this.sNodeVecs.elementAt(next);
91 this.node2Combine.add(new Vector<ScheduleNode>());
92 for(index = 0; index < toadd.size(); index++) {
93 this.node2Combine.lastElement().add(toadd.elementAt(index));
97 this.node2Combine.add(null);
101 Vector<ScheduleNode> toadd = this.sNodeVecs.elementAt(tmp);
102 if(toadd.size() > this.rootNodes.elementAt(i).size()) {
103 this.node2Combine.add(new Vector<ScheduleNode>());
104 for(index = this.rootNodes.elementAt(i).size(); index < toadd.size(); index++) {
105 this.node2Combine.lastElement().add(toadd.elementAt(index));
111 while(next < this.sNodeVecs.size()) {
112 Vector<ScheduleNode> toadd = this.sNodeVecs.elementAt(next);
114 this.node2Combine.add(new Vector<ScheduleNode>());
115 for(index = 0; index < toadd.size(); index++) {
116 this.node2Combine.lastElement().add(toadd.elementAt(index));
120 this.node2Combine.add(null);
128 private boolean trial(int num2choose, int next) {
130 boolean first = true;
131 while(num2choose > 0) {
133 if(next == this.sNodeVecs.size()) {
134 // no more nodes available to add
138 if(this.sNodeVecs.elementAt(next) != null) {
140 this.rootNodes.add(new Vector<ScheduleNode>());
143 this.rootNodes.lastElement().add(this.sNodeVecs.elementAt(next).elementAt(index));
146 if(index == this.sNodeVecs.elementAt(next).size()) {
159 public Vector<Vector<ScheduleNode>> getNode2Combine() {
163 public Vector<Vector<ScheduleNode>> getRootNodes() {
168 public class Combine {
169 public ScheduleNode node;
173 public Combine(ScheduleNode n) {
180 public class CombineGenerator {
181 Vector<Vector<ScheduleNode>> rootNodes;
182 Vector<Vector<int[]>> rootNStates;
183 Vector<Vector<ScheduleNode>> node2Combine;
184 Vector<Vector<Combine>> combine;
186 boolean first4choice;
188 public CombineGenerator(Vector<Vector<ScheduleNode>> rootnodes, Vector<Vector<ScheduleNode>> node2combine) {
189 this.rootNodes = rootnodes;
190 this.node2Combine = node2combine;
191 this.rootNStates = new Vector<Vector<int[]>>();
192 for(int i = 0; i < this.rootNodes.size(); i++) {
193 this.rootNStates.add(new Vector<int[]>());
194 for(int j = 0; j < this.rootNodes.elementAt(i).size(); j++) {
195 this.rootNStates.elementAt(i).add(new int[this.node2Combine.size()]);
196 for(int k = 0; k < this.node2Combine.size(); k++) {
197 this.rootNStates.elementAt(i).elementAt(j)[k] = 0;
201 this.combine = new Vector<Vector<Combine>>();
202 for(int i = 0; i < this.node2Combine.size(); i++) {
203 if(this.node2Combine.elementAt(i) == null) {
204 this.combine.add(null);
206 this.combine.add(new Vector<Combine>());
207 for(int j = 0; j < this.node2Combine.elementAt(i).size(); j++) {
208 this.combine.elementAt(i).add(new Combine(this.node2Combine.elementAt(i).elementAt(j)));
212 this.lastchoices = null;
213 this.first4choice = false;
216 public Vector<Vector<Combine>> getCombine() {
220 public boolean nextGen() {
221 boolean trial = false;
222 if(this.lastchoices == null) {
224 this.lastchoices = new int[this.node2Combine.size()];
225 for(int i = 0; i < this.lastchoices.length; i++) {
226 this.lastchoices[i] = 0;
228 this.first4choice = true;
233 // no more available combination under this choice
234 // choose another choice
235 int next = this.node2Combine.size() - 1;
236 boolean iter = false;
238 if(this.node2Combine.elementAt(next) != null) {
239 this.lastchoices[next]++;
240 if((this.lastchoices[next] == this.rootNodes.size() ||
241 (this.rootNodes.elementAt(this.lastchoices[next]).elementAt(0).getCid() >
242 this.node2Combine.elementAt(next).elementAt(0).getCid()))) {
243 // break the rule that a node can only be combined to nodes with smaller colorid.
244 // or no more buckets
255 } while(iter && !(next < 0));
259 for(next += 1; next < this.node2Combine.size(); next++) {
260 this.lastchoices[next] = 0;
262 this.first4choice = true;
269 private boolean trial() {
271 if(this.first4choice) {
272 // first time for each choice
273 // put all the objects of one color into the first bucket indicated by the choice
275 suc = firstexpand(next, this.first4choice);
276 this.first4choice = false;
278 int next = this.node2Combine.size() - 1;
280 suc = innertrial(next, layer);
285 private boolean firstexpand(int next, boolean first) {
286 for(int i = next; i < this.node2Combine.size(); i++) {
287 if(this.node2Combine.elementAt(i) != null) {
288 int choice = this.lastchoices[i];
289 for(int j = 0; j < this.node2Combine.elementAt(i).size(); j++) {
290 Combine tmp = this.combine.elementAt(i).elementAt(j);
292 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]--;
297 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]++;
301 this.rootNStates.elementAt(choice).elementAt(0)[i] = this.node2Combine.elementAt(i).size();
302 for(int j = 1; j < this.rootNodes.elementAt(choice).size(); j++) {
303 this.rootNStates.elementAt(choice).elementAt(j)[i] = 0;
311 private boolean innertrial(int next, int layer) {
312 if((this.combine.elementAt(next) == null) ||
313 (this.combine.elementAt(next).size() < 2)) {
314 // skip over empty buckets and bucket with only one obj ( make sure
315 // at least one obj is existing in the chosen bucket)
319 return innertrial(next - 1, ++layer);
322 Combine tmp = this.combine.elementAt(next).lastElement();
323 // try to move it backward
325 int index = tmp.index;
327 if(index == this.rootNodes.elementAt(root).size()) {
328 // no more place in this color bucket
331 } else if(this.rootNStates.elementAt(root).elementAt(index - 1)[next] <
332 this.rootNStates.elementAt(root).elementAt(index)[next] + 2) {
333 // break the law of non-increase order inside one color bucket
334 // try next bucket of another color
338 if(root == this.rootNodes.size()) {
343 int t = this.combine.elementAt(next).size() - 2;
346 tmp = this.combine.elementAt(next).elementAt(t);
347 if ((tmp.root != root) || (tmp.index != index)) {
353 // try the bucket in node2combine before
357 return innertrial(next - 1, ++layer);
359 } else if(tmp.root != root) {
360 if((tmp.root == this.lastchoices[next]) &&
361 (this.rootNStates.elementAt(this.lastchoices[next]).elementAt(0)[next] == 1)) {
362 // only 1 obj left in the chosen bucket
363 // can not move this one
364 // try the bucket in node2combine before
368 return innertrial(next - 1, ++layer);
371 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]--;
373 int newroot = tmp.root + 1;
376 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]++;
377 // make all left things in this color bucket reset
378 for(t++; t < this.combine.elementAt(next).size(); t++) {
379 tmp = this.combine.elementAt(next).elementAt(t);
380 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]--;
383 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]++;
386 return firstexpand(next+1, this.first4choice);
389 } else if(tmp.index != index) {
390 if(this.rootNStates.elementAt(root).elementAt(tmp.index)[next] ==
391 this.rootNStates.elementAt(root).elementAt(index)[next]) {
392 // break the law of non-increase order inside one color bucket
393 // go on search forward
395 } else if(this.rootNStates.elementAt(root).elementAt(tmp.index)[next] <
396 this.rootNStates.elementAt(root).elementAt(index)[next] + 2) {
397 // break the law of non-increase order inside one color bucket
398 // and now they only differ by 1
399 // propagate this difference to see if it can fix
400 boolean suc = propagateOne(next, root, index, t, tmp);
404 // go on search forward
408 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]--;
409 int tmproot = tmp.root;
410 int tmpindex = tmp.index;
413 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]++;
414 int desroot = tmp.root;
415 int desindex = tmp.index;
416 // make all left things in this color bucket reset
418 boolean first = true;
419 while(t < this.combine.elementAt(next).size()) {
425 for(; (k < this.rootNStates.elementAt(tmproot).elementAt(tmpindex)[next]) && (t < this.combine.elementAt(next).size()); t++) {
426 tmp = this.combine.elementAt(next).elementAt(t);
427 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]--;
429 tmp.index = desindex;
430 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]++;
432 if(k == this.rootNStates.elementAt(tmproot).elementAt(tmpindex)[next]) {
437 return firstexpand(next+1, this.first4choice);
444 if((tmp.root != this.lastchoices[next]) ||
445 (this.rootNStates.elementAt(this.lastchoices[next]).elementAt(0)[next] > 1)) {
446 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]--;
449 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]++;
451 return firstexpand(next+1, this.first4choice);
455 // only 1 obj with the color next exist on the chosen bucket this time,
456 // can not move it, try objs in forward color bucket
460 return innertrial(next - 1, ++layer);
466 private boolean propagateOne(int next, int rooti, int indexi, int ti, Combine tmp) {
470 int rootbk = tmp.root;
471 int indexbk = tmp.index;
472 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]--;
475 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]++;
478 if(this.rootNStates.elementAt(root).elementAt(index - 1)[next] <
479 this.rootNStates.elementAt(root).elementAt(index)[next]) {
480 // need to continue propagate
481 while(t < this.combine.elementAt(next).size()) {
482 tmpt = this.combine.elementAt(next).elementAt(t);
483 if ((tmpt.root != root) || (tmpt.index != index)) {
488 if(t == this.combine.elementAt(next).size()) {
489 // last element of this color bucket
490 if(index + 1 < this.rootNodes.elementAt(root).size()) {
491 // there is available place inside the same color bucket
492 Combine tmpbk = this.combine.elementAt(next).elementAt(t - 1);
493 boolean suc = propagateOne(next, root, index + 1, t - 1, tmpbk);
496 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]--;
499 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]++;
502 } else if(root+1 < this.rootNodes.size()) { // check if there are another bucket
504 this.rootNStates.elementAt(tmpt.root).elementAt(tmpt.index)[next]--;
505 tmpt.root = root + 1;
507 this.rootNStates.elementAt(tmpt.root).elementAt(tmpt.index)[next]++;
508 return firstexpand(next+1, this.first4choice);
511 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]--;
514 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]++;
517 } else if(tmpt.root != root) {
518 Combine tmpbk = this.combine.elementAt(next).elementAt(t - 1);
519 this.rootNStates.elementAt(tmpbk.root).elementAt(tmpbk.index)[next]--;
520 tmpbk.root = tmpt.root;
522 this.rootNStates.elementAt(tmpbk.root).elementAt(tmpbk.index)[next]++;
525 // make all left things in this color bucket reset
526 for(t += 1; t < this.combine.elementAt(next).size(); t++) {
527 tmpt = this.combine.elementAt(next).elementAt(t);
528 this.rootNStates.elementAt(tmpt.root).elementAt(tmpt.index)[next]--;
531 this.rootNStates.elementAt(tmpt.root).elementAt(tmpt.index)[next]++;
533 return firstexpand(next+1, this.first4choice);
534 } else if(tmpt.index != index) {
535 Combine tmpbk = this.combine.elementAt(next).elementAt(t - 1);
536 boolean suc = propagateOne(next, root, tmpt.index, t - 1, tmpbk);
539 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]--;
542 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]++;
546 // won't reach here, only to avoid compiler's complain