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;
43 this.sNodeVecs = null;
44 this.node2Combine.clear();
45 this.node2Combine = null;
46 this.rootNodes.clear();
47 this.rootNodes = null;
51 public boolean nextGen() {
52 boolean trial = false;
53 if(this.rootNodes == null) {
54 int num2choose = this.rootNum;
55 this.rootNodes = new Vector<Vector<ScheduleNode>>();
56 this.rootNodes.add(new Vector<ScheduleNode>());
57 Vector<ScheduleNode> toadd = this.sNodeVecs.elementAt(0);
58 for(int i = 0; i < toadd.size(); i++) {
59 // should be only one element: startup object
60 this.rootNodes.elementAt(0).add(toadd.elementAt(i));
64 trial = trial(num2choose, next);
67 if(this.rootNodes.size() == 1) {
70 int next = this.rootNodes.lastElement().elementAt(0).getCid() + 1;
72 while(next == this.sNodeVecs.size()) {
74 num2choose = this.rootNodes.lastElement().size();
75 this.rootNodes.removeElementAt(this.rootNodes.size() - 1);
76 if(this.rootNodes.size() == 1) {
77 // only startup object left, no more choices
80 next = this.rootNodes.lastElement().elementAt(0).getCid() + 1;
83 // reduce one from the last one
84 this.rootNodes.lastElement().removeElementAt(this.rootNodes.lastElement().size() - 1);
85 if(this.rootNodes.lastElement().size() == 0) {
86 this.rootNodes.removeElementAt(this.rootNodes.size() - 1);
89 trial = trial(num2choose, next);
92 // remaining nodes are all to be combined
93 this.node2Combine = new Vector<Vector<ScheduleNode>>();
96 for(int i = 1; i < this.rootNodes.size(); i++) {
97 int tmp = this.rootNodes.elementAt(i).elementAt(0).getCid();
99 Vector<ScheduleNode> toadd = this.sNodeVecs.elementAt(next);
101 this.node2Combine.add(new Vector<ScheduleNode>());
102 for(index = 0; index < toadd.size(); index++) {
103 this.node2Combine.lastElement().add(toadd.elementAt(index));
107 this.node2Combine.add(null);
111 Vector<ScheduleNode> toadd = this.sNodeVecs.elementAt(tmp);
112 if(toadd.size() > this.rootNodes.elementAt(i).size()) {
113 this.node2Combine.add(new Vector<ScheduleNode>());
114 for(index = this.rootNodes.elementAt(i).size(); index < toadd.size(); index++) {
115 this.node2Combine.lastElement().add(toadd.elementAt(index));
121 while(next < this.sNodeVecs.size()) {
122 Vector<ScheduleNode> toadd = this.sNodeVecs.elementAt(next);
124 this.node2Combine.add(new Vector<ScheduleNode>());
125 for(index = 0; index < toadd.size(); index++) {
126 this.node2Combine.lastElement().add(toadd.elementAt(index));
130 this.node2Combine.add(null);
138 private boolean trial(int num2choose,
141 boolean first = true;
142 while(num2choose > 0) {
144 if(next == this.sNodeVecs.size()) {
145 // no more nodes available to add
149 if(this.sNodeVecs.elementAt(next) != null) {
151 this.rootNodes.add(new Vector<ScheduleNode>());
154 this.rootNodes.lastElement().add(this.sNodeVecs.elementAt(next).elementAt(index));
157 if(index == this.sNodeVecs.elementAt(next).size()) {
170 public Vector<Vector<ScheduleNode>> getNode2Combine() {
174 public Vector<Vector<ScheduleNode>> getRootNodes() {
179 public class Combine {
180 public ScheduleNode node;
184 public Combine(ScheduleNode n) {
191 public class CombineGenerator {
192 Vector<Vector<ScheduleNode>> rootNodes;
193 Vector<Vector<int[]>> rootNStates;
194 Vector<Vector<ScheduleNode>> node2Combine;
195 Vector<Vector<Combine>> combine;
197 boolean first4choice;
199 public CombineGenerator(Vector<Vector<ScheduleNode>> rootnodes,
200 Vector<Vector<ScheduleNode>> node2combine) {
201 this.rootNodes = rootnodes;
202 this.node2Combine = node2combine;
203 this.rootNStates = new Vector<Vector<int[]>>();
204 for(int i = 0; i < this.rootNodes.size(); i++) {
205 this.rootNStates.add(new Vector<int[]>());
206 for(int j = 0; j < this.rootNodes.elementAt(i).size(); j++) {
207 this.rootNStates.elementAt(i).add(new int[this.node2Combine.size()]);
208 for(int k = 0; k < this.node2Combine.size(); k++) {
209 this.rootNStates.elementAt(i).elementAt(j)[k] = 0;
213 this.combine = new Vector<Vector<Combine>>();
214 for(int i = 0; i < this.node2Combine.size(); i++) {
215 if(this.node2Combine.elementAt(i) == null) {
216 this.combine.add(null);
218 this.combine.add(new Vector<Combine>());
219 for(int j = 0; j < this.node2Combine.elementAt(i).size(); j++) {
220 this.combine.elementAt(i).add(new Combine(this.node2Combine.elementAt(i).elementAt(j)));
224 this.lastchoices = null;
225 this.first4choice = false;
228 public void clear() {
229 this.rootNodes = null;
230 this.rootNStates.clear();
231 this.rootNStates = null;
232 this.node2Combine = null;
233 this.combine.clear();
235 this.lastchoices = null;
236 this.first4choice = false;
239 public Vector<Vector<Combine>> getCombine() {
243 public boolean nextGen() {
244 boolean trial = false;
245 if(this.lastchoices == null) {
247 this.lastchoices = new int[this.node2Combine.size()];
248 for(int i = 0; i < this.lastchoices.length; i++) {
249 this.lastchoices[i] = 0;
251 this.first4choice = true;
256 // no more available combination under this choice
257 // choose another choice
258 int next = this.node2Combine.size() - 1;
259 boolean iter = false;
261 if(this.node2Combine.elementAt(next) != null) {
262 this.lastchoices[next]++;
263 if((this.lastchoices[next] == this.rootNodes.size() ||
264 (this.rootNodes.elementAt(this.lastchoices[next]).elementAt(0).getCid() >
265 this.node2Combine.elementAt(next).elementAt(0).getCid()))) {
266 // break the rule that a node can only be combined to nodes with smaller colorid.
267 // or no more buckets
278 } while(iter && !(next < 0));
282 for(next += 1; next < this.node2Combine.size(); next++) {
283 this.lastchoices[next] = 0;
285 this.first4choice = true;
292 private boolean trial() {
294 if(this.first4choice) {
295 // first time for each choice
296 // put all the objects of one color into the first bucket indicated by the choice
298 suc = firstexpand(next, this.first4choice);
299 this.first4choice = false;
301 int next = this.node2Combine.size() - 1;
303 suc = innertrial(next, layer);
308 private boolean firstexpand(int next,
310 for(int i = next; i < this.node2Combine.size(); i++) {
311 if(this.node2Combine.elementAt(i) != null) {
312 int choice = this.lastchoices[i];
313 for(int j = 0; j < this.node2Combine.elementAt(i).size(); j++) {
314 Combine tmp = this.combine.elementAt(i).elementAt(j);
316 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]--;
321 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]++;
325 this.rootNStates.elementAt(choice).elementAt(0)[i] = this.node2Combine.elementAt(i).size();
326 for(int j = 1; j < this.rootNodes.elementAt(choice).size(); j++) {
327 this.rootNStates.elementAt(choice).elementAt(j)[i] = 0;
335 private boolean innertrial(int next,
337 if((this.combine.elementAt(next) == null) ||
338 (this.combine.elementAt(next).size() < 2)) {
339 // skip over empty buckets and bucket with only one obj ( make sure
340 // at least one obj is existing in the chosen bucket)
344 return innertrial(next - 1, ++layer);
347 Combine tmp = this.combine.elementAt(next).lastElement();
348 // try to move it backward
350 int index = tmp.index;
352 if(index == this.rootNodes.elementAt(root).size()) {
353 // no more place in this color bucket
356 } else if(this.rootNStates.elementAt(root).elementAt(index - 1)[next] <
357 this.rootNStates.elementAt(root).elementAt(index)[next] + 2) {
358 // break the law of non-increase order inside one color bucket
359 // try next bucket of another color
363 if(root == this.rootNodes.size()) {
368 int t = this.combine.elementAt(next).size() - 2;
371 tmp = this.combine.elementAt(next).elementAt(t);
372 if ((tmp.root != root) || (tmp.index != index)) {
378 // try the bucket in node2combine before
382 return innertrial(next - 1, ++layer);
384 } else if(tmp.root != root) {
385 if((tmp.root == this.lastchoices[next]) &&
386 (this.rootNStates.elementAt(this.lastchoices[next]).elementAt(0)[next] == 1)) {
387 // only 1 obj left in the chosen bucket
388 // can not move this one
389 // try the bucket in node2combine before
393 return innertrial(next - 1, ++layer);
396 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]--;
398 int newroot = tmp.root + 1;
401 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]++;
402 // make all left things in this color bucket reset
403 for(t++; t < this.combine.elementAt(next).size(); t++) {
404 tmp = this.combine.elementAt(next).elementAt(t);
405 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]--;
408 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]++;
411 return firstexpand(next+1, this.first4choice);
414 } else if(tmp.index != index) {
415 if(this.rootNStates.elementAt(root).elementAt(tmp.index)[next] ==
416 this.rootNStates.elementAt(root).elementAt(index)[next]) {
417 // break the law of non-increase order inside one color bucket
418 // go on search forward
420 } else if(this.rootNStates.elementAt(root).elementAt(tmp.index)[next] <
421 this.rootNStates.elementAt(root).elementAt(index)[next] + 2) {
422 // break the law of non-increase order inside one color bucket
423 // and now they only differ by 1
424 // propagate this difference to see if it can fix
425 boolean suc = propagateOne(next, root, index, t, tmp);
429 // go on search forward
433 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]--;
434 int tmproot = tmp.root;
435 int tmpindex = tmp.index;
438 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]++;
439 int desroot = tmp.root;
440 int desindex = tmp.index;
441 // make all left things in this color bucket reset
443 boolean first = true;
444 while(t < this.combine.elementAt(next).size()) {
450 for(; (k < this.rootNStates.elementAt(tmproot).elementAt(tmpindex)[next]) && (t < this.combine.elementAt(next).size()); t++) {
451 tmp = this.combine.elementAt(next).elementAt(t);
452 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]--;
454 tmp.index = desindex;
455 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]++;
457 if(k == this.rootNStates.elementAt(tmproot).elementAt(tmpindex)[next]) {
462 return firstexpand(next+1, this.first4choice);
469 if((tmp.root != this.lastchoices[next]) ||
470 (this.rootNStates.elementAt(this.lastchoices[next]).elementAt(0)[next] > 1)) {
471 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]--;
474 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]++;
476 return firstexpand(next+1, this.first4choice);
480 // only 1 obj with the color next exist on the chosen bucket this time,
481 // can not move it, try objs in forward color bucket
485 return innertrial(next - 1, ++layer);
491 private boolean propagateOne(int next,
499 int rootbk = tmp.root;
500 int indexbk = tmp.index;
501 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]--;
504 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]++;
507 if(this.rootNStates.elementAt(root).elementAt(index - 1)[next] <
508 this.rootNStates.elementAt(root).elementAt(index)[next]) {
509 // need to continue propagate
510 while(t < this.combine.elementAt(next).size()) {
511 tmpt = this.combine.elementAt(next).elementAt(t);
512 if ((tmpt.root != root) || (tmpt.index != index)) {
517 if(t == this.combine.elementAt(next).size()) {
518 // last element of this color bucket
519 if(index + 1 < this.rootNodes.elementAt(root).size()) {
520 // there is available place inside the same color bucket
521 Combine tmpbk = this.combine.elementAt(next).elementAt(t - 1);
522 boolean suc = propagateOne(next, root, index + 1, t - 1, tmpbk);
525 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]--;
528 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]++;
531 } else if(root+1 < this.rootNodes.size()) { // check if there are another bucket
533 this.rootNStates.elementAt(tmpt.root).elementAt(tmpt.index)[next]--;
534 tmpt.root = root + 1;
536 this.rootNStates.elementAt(tmpt.root).elementAt(tmpt.index)[next]++;
537 return firstexpand(next+1, this.first4choice);
540 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]--;
543 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]++;
546 } else if(tmpt.root != root) {
547 Combine tmpbk = this.combine.elementAt(next).elementAt(t - 1);
548 this.rootNStates.elementAt(tmpbk.root).elementAt(tmpbk.index)[next]--;
549 tmpbk.root = tmpt.root;
551 this.rootNStates.elementAt(tmpbk.root).elementAt(tmpbk.index)[next]++;
554 // make all left things in this color bucket reset
555 for(t += 1; t < this.combine.elementAt(next).size(); t++) {
556 tmpt = this.combine.elementAt(next).elementAt(t);
557 this.rootNStates.elementAt(tmpt.root).elementAt(tmpt.index)[next]--;
560 this.rootNStates.elementAt(tmpt.root).elementAt(tmpt.index)[next]++;
562 return firstexpand(next+1, this.first4choice);
563 } else if(tmpt.index != index) {
564 Combine tmpbk = this.combine.elementAt(next).elementAt(t - 1);
565 boolean suc = propagateOne(next, root, tmpt.index, t - 1, tmpbk);
568 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]--;
571 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]++;
575 // won't reach here, only to avoid compiler's complain