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);
54 int next = this.rootNodes.lastElement().elementAt(0).getCid() + 1;
56 if(next == this.sNodeVecs.size()) {
58 num2choose = this.rootNodes.lastElement().size();
59 this.rootNodes.removeElementAt(this.rootNodes.size() - 1);
60 if(this.rootNodes.size() == 1) {
61 // only startup object left, no more choices
64 next = this.rootNodes.lastElement().elementAt(0).getCid() + 1;
68 // reduce one from the last one
69 this.rootNodes.lastElement().removeElementAt(this.rootNodes.lastElement().size() - 1);
70 if(this.rootNodes.lastElement().size() == 0) {
71 this.rootNodes.removeElementAt(this.rootNodes.size() - 1);
74 trial = trial(num2choose, next);
77 // left nodes are all to be combined
78 this.node2Combine = new Vector<Vector<ScheduleNode>>();
81 for(int i = 1; i < this.rootNodes.size(); i++) {
82 int tmp = this.rootNodes.elementAt(i).elementAt(0).getCid();
84 this.node2Combine.add(new Vector<ScheduleNode>());
85 Vector<ScheduleNode> toadd = this.sNodeVecs.elementAt(next);
86 for(index = 0; index < toadd.size(); index++) {
87 this.node2Combine.lastElement().add(toadd.elementAt(index));
91 Vector<ScheduleNode> toadd = this.sNodeVecs.elementAt(tmp);
92 if(toadd.size() > this.rootNodes.elementAt(i).size()) {
93 this.node2Combine.add(new Vector<ScheduleNode>());
94 for(index = this.rootNodes.elementAt(i).size(); index < toadd.size(); index++) {
95 this.node2Combine.lastElement().add(toadd.elementAt(index));
100 while(next < this.sNodeVecs.size()) {
101 this.node2Combine.add(new Vector<ScheduleNode>());
102 Vector<ScheduleNode> toadd = this.sNodeVecs.elementAt(next);
103 for(index = 0; index < toadd.size(); index++) {
104 this.node2Combine.lastElement().add(toadd.elementAt(index));
112 private boolean trial(int num2choose, int next) {
114 boolean first = true;
115 while(num2choose > 0) {
117 if(next == this.sNodeVecs.size()) {
118 // no more nodes available to add
121 this.rootNodes.add(new Vector<ScheduleNode>());
124 this.rootNodes.lastElement().add(this.sNodeVecs.elementAt(next).elementAt(index));
127 if(index == this.sNodeVecs.elementAt(next).size()) {
136 public Vector<Vector<ScheduleNode>> getNode2Combine() {
140 public Vector<Vector<ScheduleNode>> getRootNodes() {
145 public class Combine {
146 public ScheduleNode node;
150 public Combine(ScheduleNode n) {
157 public class CombineGenerator {
158 Vector<Vector<ScheduleNode>> rootNodes;
159 Vector<Vector<int[]>> rootNStates;
160 Vector<Vector<ScheduleNode>> node2Combine;
161 Vector<Vector<Combine>> combine;
163 boolean first4choice;
165 public CombineGenerator(Vector<Vector<ScheduleNode>> rootnodes, Vector<Vector<ScheduleNode>> node2combine) {
166 this.rootNodes = rootnodes;
167 this.node2Combine = node2combine;
168 this.rootNStates = new Vector<Vector<int[]>>();
169 for(int i = 0; i < this.rootNodes.size(); i++) {
170 this.rootNStates.add(new Vector<int[]>());
171 for(int j = 0; j < this.rootNodes.elementAt(i).size(); j++) {
172 this.rootNStates.elementAt(i).add(new int[this.node2Combine.size()]);
173 for(int k = 0; k < this.node2Combine.size(); k++) {
174 this.rootNStates.elementAt(i).elementAt(j)[k] = 0;
178 this.combine = new Vector<Vector<Combine>>();
179 for(int i = 0; i < this.node2Combine.size(); i++) {
180 this.combine.add(new Vector<Combine>());
181 for(int j = 0; j < this.node2Combine.elementAt(i).size(); j++) {
182 this.combine.elementAt(i).add(new Combine(this.node2Combine.elementAt(i).elementAt(j)));
185 this.lastchoices = null;
186 this.first4choice = false;
189 public Vector<Vector<Combine>> getCombine() {
193 public boolean nextGen() {
194 boolean trial = false;
195 if(this.lastchoices == null) {
197 this.lastchoices = new int[this.node2Combine.size()];
198 for(int i = 0; i < this.lastchoices.length; i++) {
199 this.lastchoices[i] = 0;
201 this.first4choice = true;
206 // no more available combination under this choice
207 // choose another choice
208 int next = this.node2Combine.size() - 1;
209 boolean iter = false;;
211 this.lastchoices[next]++;
212 if(this.lastchoices[next] > this.node2Combine.elementAt(next).elementAt(0).getCid()) {
213 // break the rule that a node can only be combined to nodes with smaller colorid.
220 }while(iter && !(next < 0));
224 for(next += 1; next < this.node2Combine.size(); next++) {
225 this.lastchoices[next] = 0;
227 this.first4choice = true;
234 private boolean trial() {
236 if(this.first4choice) {
237 // first time for each choice
238 // put all the objects of one color into the first bucket indicated by the choice
240 suc = firstexpand(next, this.first4choice);
241 this.first4choice = false;
243 int next = this.node2Combine.size() - 1;
245 suc = innertrial(next, layer);
250 private boolean firstexpand(int next, boolean first) {
251 for(int i = next; i < this.node2Combine.size(); i++) {
252 int choice = this.lastchoices[i];
253 for(int j = 0; j < this.node2Combine.elementAt(i).size(); j++) {
254 Combine tmp = this.combine.elementAt(i).elementAt(j);
256 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]--;
261 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]++;
265 this.rootNStates.elementAt(choice).elementAt(0)[i] = this.node2Combine.elementAt(i).size();
266 for(int j = 1; j < this.rootNodes.elementAt(choice).size(); j++) {
267 this.rootNStates.elementAt(choice).elementAt(j)[i] = 0;
274 private boolean innertrial(int next, int layer) {
275 Combine tmp = this.combine.elementAt(next).lastElement();
276 // try to move it backward
278 int index = tmp.index;
280 if(index == this.rootNodes.elementAt(root).size()) {
281 // no more place in this color bucket
284 }else if(this.rootNStates.elementAt(root).elementAt(index - 1)[next] <
285 this.rootNStates.elementAt(root).elementAt(index)[next] + 2) {
286 // break the law of non-increase order inside one color bucket
287 // try next bucket of another color
291 if(root == this.rootNodes.size()) {
296 int t = this.combine.elementAt(next).size() - 2;
299 tmp = this.combine.elementAt(next).elementAt(t);
300 if ((tmp.root != root) || (tmp.index != index)) {
306 // try the bucket in node2combine before
310 return innertrial(next - 1, ++layer);
312 } else if(tmp.root != root) {
313 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]--;
316 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]++;
317 // make all left things in this color bucket reset
318 for(t += 1; t < this.combine.elementAt(next).size(); t++) {
319 tmp = this.combine.elementAt(next).elementAt(t);
320 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]--;
323 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]++;
326 return firstexpand(next+1, this.first4choice);
329 } else if(tmp.index != index) {
330 if(this.rootNStates.elementAt(root).elementAt(tmp.index)[next] ==
331 this.rootNStates.elementAt(root).elementAt(index)[next]) {
332 // break the law of non-increase order inside one color bucket
333 // go on search forward
335 } else if(this.rootNStates.elementAt(root).elementAt(tmp.index)[next] <
336 this.rootNStates.elementAt(root).elementAt(index)[next] + 2) {
337 // break the law of non-increase order inside one color bucket
338 // and now they only differ by 1
339 // propagate this difference to see if it can fix
340 boolean suc = propagateOne(next, root, index, t, tmp);
344 // go on search forward
348 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]--;
351 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]++;
353 return firstexpand(next+1, this.first4choice);
360 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]--;
363 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]++;
365 return firstexpand(next+1, this.first4choice);
371 private boolean propagateOne(int next, int rooti, int indexi, int ti, Combine tmp) {
375 int rootbk = tmp.root;
376 int indexbk = tmp.index;
377 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]--;
380 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]++;
382 if(this.rootNStates.elementAt(root).elementAt(index - 1)[next] <
383 this.rootNStates.elementAt(root).elementAt(index)[next]) {
384 // need to continue propagate
385 while(t < this.combine.elementAt(next).size()) {
386 tmp = this.combine.elementAt(next).elementAt(t);
387 if ((tmp.root != root) || (tmp.index != index)) {
392 if(t == this.combine.elementAt(next).size()) {
393 if(index + 1 < this.rootNodes.elementAt(root).size()) {
394 // there is available place inside the same color bucket
395 Combine tmpbk = this.combine.elementAt(next).elementAt(t - 1);
396 boolean suc = propagateOne(next, root, index + 1, t - 1, tmpbk);
399 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]--;
402 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]++;
405 } else if(root+1 < this.rootNodes.size()) { // check if there are another bucket
407 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]--;
410 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]++;
411 return firstexpand(next+1, this.first4choice);
414 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]--;
417 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]++;
420 } else if(tmp.root != root) {
421 Combine tmpbk = this.combine.elementAt(next).elementAt(t - 1);
422 this.rootNStates.elementAt(tmpbk.root).elementAt(tmpbk.index)[next]--;
423 tmpbk.root = tmp.root;
426 this.rootNStates.elementAt(tmpbk.root).elementAt(tmpbk.index)[next]++;
428 // make all left things in this color bucket reset
429 for(t += 1; t < this.combine.elementAt(next).size(); t++) {
430 tmp = this.combine.elementAt(next).elementAt(t);
431 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]--;
434 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]++;
436 return firstexpand(next+1, this.first4choice);
437 } else if(tmp.index != index) {
438 Combine tmpbk = this.combine.elementAt(next).elementAt(t - 1);
439 boolean suc = propagateOne(next, root, tmp.index, t - 1, tmpbk);
442 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]--;
445 this.rootNStates.elementAt(tmp.root).elementAt(tmp.index)[next]++;
449 // won't reach here, only to avoid compiler's complain