1 package Analysis.Scheduling;
3 import Analysis.TaskStateAnalysis.*;
4 import Analysis.TaskStateAnalysis.FEdge.NewObjInfo;
11 import Util.GraphNode;
14 /** This class holds flag transition diagram(s) can be put on one core.
16 public class ScheduleAnalysis {
18 TaskAnalysis taskanalysis;
20 Vector<ScheduleNode> scheduleNodes;
21 Vector<ClassNode> classNodes;
22 Hashtable<ClassDescriptor, ClassNode> cd2ClassNode;
23 boolean sorted = false;
24 Vector<ScheduleEdge> scheduleEdges;
29 Vector<Vector<ScheduleNode>> schedules;
31 public ScheduleAnalysis(State state, TaskAnalysis taskanalysis) {
33 this.taskanalysis = taskanalysis;
34 this.scheduleNodes = new Vector<ScheduleNode>();
35 this.classNodes = new Vector<ClassNode>();
36 this.scheduleEdges = new Vector<ScheduleEdge>();
37 this.cd2ClassNode = new Hashtable<ClassDescriptor, ClassNode>();
38 this.transThreshold = 45;
42 public void setTransThreshold(int tt) {
43 this.transThreshold = tt;
46 public void setCoreNum(int coreNum) {
47 this.coreNum = coreNum;
50 public Iterator getSchedules() {
51 return this.schedules.iterator();
55 public Vector<ScheduleEdge> getSEdges4Test() {
59 public void preSchedule() {
60 Hashtable<ClassDescriptor, ClassNode> cdToCNodes = new Hashtable<ClassDescriptor, ClassNode>();
61 // Build the combined flag transition diagram
62 // First, for each class create a ClassNode
63 for(Iterator it_classes = state.getClassSymbolTable().getDescriptorsIterator(); it_classes.hasNext(); ) {
64 ClassDescriptor cd = (ClassDescriptor) it_classes.next();
65 Set<FlagState> fStates = taskanalysis.getFlagStates(cd);
67 //Sort flagState nodes inside this ClassNode
68 Vector<FlagState> sFStates = FlagState.DFS.topology(fStates, null);
70 Vector rootnodes = taskanalysis.getRootNodes(cd);
71 if(((rootnodes != null) && (rootnodes.size() > 0)) || (cd.getSymbol().equals("StartupObject"))) {
72 ClassNode cNode = new ClassNode(cd, sFStates);
73 cNode.setSorted(true);
74 classNodes.add(cNode);
75 cd2ClassNode.put(cd, cNode);
76 cdToCNodes.put(cd, cNode);
80 if(cd.getSymbol().equals("C")) {
81 cNode.setTransTime(45);
88 // For each ClassNode create a ScheduleNode containing it
90 for(i = 0; i < classNodes.size(); i++) {
91 ScheduleNode sn = new ScheduleNode(classNodes.elementAt(i), 0);
92 classNodes.elementAt(i).setScheduleNode(sn);
93 scheduleNodes.add(sn);
96 } catch (Exception e) {
101 // Create 'new' edges between the ScheduleNodes.
102 Vector<ScheduleEdge> toBreakDown = new Vector<ScheduleEdge>();
103 for(i = 0; i < classNodes.size(); i++) {
104 ClassNode cNode = classNodes.elementAt(i);
105 ClassDescriptor cd = cNode.getClassDescriptor();
106 Vector rootnodes = taskanalysis.getRootNodes(cd);
107 if(rootnodes != null) {
108 for(int h = 0; h < rootnodes.size(); h++){
109 FlagState root=(FlagState)rootnodes.elementAt(h);
110 Vector allocatingTasks = root.getAllocatingTasks();
111 if(allocatingTasks != null) {
112 for(int k = 0; k < allocatingTasks.size(); k++) {
113 TaskDescriptor td = (TaskDescriptor)allocatingTasks.elementAt(k);
114 Vector<FEdge> fev = (Vector<FEdge>)taskanalysis.getFEdgesFromTD(td);
115 int numEdges = fev.size();
116 ScheduleNode sNode = cNode.getScheduleNode();
117 for(int j = 0; j < numEdges; j++) {
118 FEdge pfe = fev.elementAt(j);
119 FEdge.NewObjInfo noi = pfe.getNewObjInfo(cd);
120 if ((noi == null) || (noi.getNewRate() == 0) || (noi.getProbability() == 0)) {
121 // fake creating edge, do not need to create corresponding 'new' edge
124 FlagState pfs = (FlagState)pfe.getTarget();
125 ClassDescriptor pcd = pfs.getClassDescriptor();
126 ClassNode pcNode = cdToCNodes.get(pcd);
128 ScheduleEdge sEdge = new ScheduleEdge(sNode, "new", cd, 0);
130 sEdge.setSourceCNode(pcNode);
131 sEdge.setTargetCNode(cNode);
132 sEdge.setTargetFState(root);
133 sEdge.setNewRate(noi.getNewRate());
134 sEdge.setProbability(noi.getProbability());
135 pcNode.getScheduleNode().addEdge(sEdge);
136 scheduleEdges.add(sEdge);
137 if((j !=0 ) || (k != 0) || (h != 0)) {
138 toBreakDown.add(sEdge);
143 allocatingTasks = null;
151 // Do topology sort of the ClassNodes and ScheduleEdges.
152 Vector<ScheduleEdge> ssev = new Vector<ScheduleEdge>();
153 Vector<ScheduleNode> tempSNodes = ClassNode.DFS.topology(scheduleNodes, ssev);
154 scheduleNodes.removeAllElements();
155 scheduleNodes = tempSNodes;
157 scheduleEdges.removeAllElements();
158 scheduleEdges = ssev;
162 // Break down the 'cycle's
163 for(i = 0; i < toBreakDown.size(); i++ ) {
164 cloneSNodeList(toBreakDown.elementAt(i), false);
168 // Remove fake 'new' edges
169 for(i = 0; i < scheduleEdges.size(); i++) {
170 ScheduleEdge se = scheduleEdges.elementAt(i);
171 if((0 == se.getNewRate()) || (0 == se.getProbability())) {
172 scheduleEdges.removeElement(se);
173 scheduleNodes.removeElement(se.getTarget());
177 printScheduleGraph("scheduling_ori.dot", this.scheduleNodes);
180 public void scheduleAnalysis() {
183 //Access the ScheduleEdges in reverse topology order
184 Hashtable<FEdge, Vector<ScheduleEdge>> fe2ses = new Hashtable<FEdge, Vector<ScheduleEdge>>();
185 Hashtable<ScheduleNode, Vector<FEdge>> sn2fes = new Hashtable<ScheduleNode, Vector<FEdge>>();
186 ScheduleNode preSNode = null;
187 for(i = scheduleEdges.size(); i > 0; i--) {
188 ScheduleEdge se = scheduleEdges.elementAt(i-1);
189 if(preSNode == null) {
190 preSNode = (ScheduleNode)se.getSource();
193 boolean split = false;
194 FEdge fe = se.getFEdge();
195 if(fe.getSource() == fe.getTarget()) {
197 int repeat = (int)Math.ceil(se.getNewRate() * se.getProbability() / 100);
200 for(int j = 1; j< repeat; j++ ) {
201 cloneSNodeList(se, true);
204 se.setProbability(100);
207 rate = (int)Math.ceil(se.getListExeTime()/ calInExeTime(se.getSourceFState()));
208 } catch (Exception e) {
211 for(int j = rate - 1; j > 0; j--) {
212 for(int k = repeat; k > 0; k--) {
213 cloneSNodeList(se, true);
217 // if preSNode is not the same as se's source ScheduleNode
218 // handle any ScheduleEdges previously put into fe2ses whose source ScheduleNode is preSNode
219 boolean same = (preSNode == se.getSource());
221 if(preSNode.getFinishingTime() < se.getSource().getFinishingTime()) {
222 if(sn2fes.containsKey(preSNode)) {
223 Vector<FEdge> fes = sn2fes.remove(preSNode);
224 for(int j = 0; j < fes.size(); j++) {
225 FEdge tempfe = fes.elementAt(j);
226 Vector<ScheduleEdge> ses = fe2ses.get(tempfe);
227 ScheduleEdge tempse = ses.elementAt(0);
228 int temptime = tempse.getListExeTime();
229 // find out the ScheduleEdge with least exeTime
230 for(int k = 1; k < ses.size(); k++) {
231 int ttemp = ses.elementAt(k).getListExeTime();
232 if(ttemp < temptime) {
233 tempse = ses.elementAt(k);
238 handleScheduleEdge(tempse, true);
239 ses.removeElement(tempse);
240 // handle other ScheduleEdges
241 for(int k = 0; k < ses.size(); k++) {
242 handleScheduleEdge(ses.elementAt(k), false);
245 fe2ses.remove(tempfe);
250 preSNode = (ScheduleNode)se.getSource();
253 // if fe is the last task inside this ClassNode, delay the expanding and merging until we find all such 'nmew' edges
254 // associated with a last task inside this ClassNode
255 if(!fe.getTarget().edges().hasNext()) {
256 if(fe2ses.get(fe) == null) {
257 fe2ses.put(fe, new Vector<ScheduleEdge>());
259 if(sn2fes.get((ScheduleNode)se.getSource()) == null) {
260 sn2fes.put((ScheduleNode)se.getSource(), new Vector<FEdge>());
262 fe2ses.get(fe).add(se);
263 sn2fes.get((ScheduleNode)se.getSource()).add(fe);
265 // As this is not a last task, first handle available ScheduleEdges previously put into fe2ses
266 if((same) && (sn2fes.containsKey(preSNode))) {
267 Vector<FEdge> fes = sn2fes.remove(preSNode);
268 for(int j = 0; j < fes.size(); j++) {
269 FEdge tempfe = fes.elementAt(j);
270 Vector<ScheduleEdge> ses = fe2ses.get(tempfe);
271 ScheduleEdge tempse = ses.elementAt(0);
272 int temptime = tempse.getListExeTime();
273 // find out the ScheduleEdge with least exeTime
274 for(int k = 1; k < ses.size(); k++) {
275 int ttemp = ses.elementAt(k).getListExeTime();
276 if(ttemp < temptime) {
277 tempse = ses.elementAt(k);
282 handleScheduleEdge(tempse, true);
283 ses.removeElement(tempse);
284 // handle other ScheduleEdges
285 for(int k = 0; k < ses.size(); k++) {
286 handleScheduleEdge(ses.elementAt(k), false);
289 fe2ses.remove(tempfe);
294 if((!(se.getTransTime() < this.transThreshold)) && (se.getSourceCNode().getTransTime() < se.getTransTime())) {
296 splitSNode(se, true);
298 // handle this ScheduleEdge
299 handleScheduleEdge(se, true);
305 if(!fe2ses.isEmpty()) {
306 Set<FEdge> keys = fe2ses.keySet();
307 Iterator it_keys = keys.iterator();
308 while(it_keys.hasNext()) {
309 FEdge tempfe = (FEdge)it_keys.next();
310 Vector<ScheduleEdge> ses = fe2ses.get(tempfe);
311 ScheduleEdge tempse = ses.elementAt(0);
312 int temptime = tempse.getListExeTime();
313 // find out the ScheduleEdge with least exeTime
314 for(int k = 1; k < ses.size(); k++) {
315 int ttemp = ses.elementAt(k).getListExeTime();
316 if(ttemp < temptime) {
317 tempse = ses.elementAt(k);
322 handleScheduleEdge(tempse, true);
323 ses.removeElement(tempse);
324 // handle other ScheduleEdges
325 for(int k = 0; k < ses.size(); k++) {
326 handleScheduleEdge(ses.elementAt(k), false);
337 printScheduleGraph("scheduling_extend.dot", this.scheduleNodes);
340 private void handleScheduleEdge(ScheduleEdge se, boolean merge) {
342 int repeat = (int)Math.ceil(se.getNewRate() * se.getProbability() / 100);
345 rate = (int)Math.ceil((se.getTransTime() - calInExeTime(se.getSourceFState()))/ se.getListExeTime());
349 } catch (Exception e) {
353 // clone the whole ScheduleNode lists starting with se's target
354 for(int j = 1; j < repeat; j++ ) {
355 cloneSNodeList(se, true);
358 se.setProbability(100);
362 // clone the whole ScheduleNode lists starting with se's target
363 for(int j = 0; j < repeat; j++ ) {
364 cloneSNodeList(se, true);
367 se.setProbability(100);
370 // merge the original ScheduleNode to the source ScheduleNode
371 ((ScheduleNode)se.getSource()).mergeSEdge(se);
372 scheduleNodes.remove(se.getTarget());
373 scheduleEdges.remove(se);
374 // As se has been changed into an internal edge inside a ScheduleNode,
375 // change the source and target of se from original ScheduleNodes into ClassNodes.
376 se.setTarget(se.getTargetCNode());
377 se.setSource(se.getSourceCNode());
379 // clone the whole ScheduleNode lists starting with se's target
380 for(int j = 1; j < repeat; j++ ) {
381 cloneSNodeList(se, true);
384 se.setProbability(100);
388 private void cloneSNodeList(ScheduleEdge sEdge, boolean copyIE) {
389 Hashtable<ClassNode, ClassNode> cn2cn = new Hashtable<ClassNode, ClassNode>();
390 ScheduleNode csNode = (ScheduleNode)((ScheduleNode)sEdge.getTarget()).clone(cn2cn, 0);
391 scheduleNodes.add(csNode);
393 // Clone all the external in ScheduleEdges
396 Vector inedges = sEdge.getTarget().getInedgeVector();
397 for(i = 0; i < inedges.size(); i++) {
398 ScheduleEdge tse = (ScheduleEdge)inedges.elementAt(i);
401 se = new ScheduleEdge(csNode, "new", tse.getClassDescriptor(), tse.getIsNew(), 0);
402 se.setProbability(100);
404 se.setFEdge(tse.getFEdge());
406 se = new ScheduleEdge(csNode, "transmit", tse.getClassDescriptor(), false, 0);
408 se.setSourceCNode(tse.getSourceCNode());
409 se.setTargetCNode(cn2cn.get(tse.getTargetCNode()));
410 tse.getSource().addEdge(se);
411 scheduleEdges.add(se);
415 sEdge.getTarget().removeInedge(sEdge);
416 sEdge.setTarget(csNode);
417 csNode.getInedgeVector().add(sEdge);
418 sEdge.setTargetCNode(cn2cn.get(sEdge.getTargetCNode()));
419 sEdge.setTargetFState(null);
422 Queue<ScheduleNode> toClone = new LinkedList<ScheduleNode>();
423 Queue<ScheduleNode> clone = new LinkedList<ScheduleNode>();
424 Queue<Hashtable> qcn2cn = new LinkedList<Hashtable>();
426 toClone.add((ScheduleNode)sEdge.getTarget());
428 while(!toClone.isEmpty()) {
429 Hashtable<ClassNode, ClassNode> tocn2cn = new Hashtable<ClassNode, ClassNode>();
430 csNode = clone.poll();
431 ScheduleNode osNode = toClone.poll();
432 cn2cn = qcn2cn.poll();
433 // Clone all the external ScheduleEdges and the following ScheduleNodes
434 Vector edges = osNode.getEdgeVector();
435 for(i = 0; i < edges.size(); i++) {
436 ScheduleEdge tse = (ScheduleEdge)edges.elementAt(i);
437 ScheduleNode tSNode = (ScheduleNode)((ScheduleNode)tse.getTarget()).clone(tocn2cn, 0);
438 scheduleNodes.add(tSNode);
440 toClone.add((ScheduleNode)tse.getTarget());
442 ScheduleEdge se = null;
444 se = new ScheduleEdge(tSNode, "new", tse.getClassDescriptor(), tse.getIsNew(), 0);
445 se.setProbability(tse.getProbability());
446 se.setNewRate(tse.getNewRate());
448 se = new ScheduleEdge(tSNode, "transmit", tse.getClassDescriptor(), false, 0);
450 se.setSourceCNode(cn2cn.get(tse.getSourceCNode()));
451 se.setTargetCNode(tocn2cn.get(tse.getTargetCNode()));
453 scheduleEdges.add(se);
464 private int calInExeTime(FlagState fs) throws Exception {
466 ClassDescriptor cd = fs.getClassDescriptor();
467 ClassNode cNode = cd2ClassNode.get(cd);
468 exeTime = cNode.getFlagStates().elementAt(0).getExeTime() - fs.getExeTime();
470 Vector inedges = cNode.getInedgeVector();
471 if(inedges.size() > 1) {
472 throw new Exception("Error: ClassNode's inedges more than one!");
474 if(inedges.size() > 0) {
475 ScheduleEdge sEdge = (ScheduleEdge)inedges.elementAt(0);
476 cNode = (ClassNode)sEdge.getSource();
477 exeTime += cNode.getFlagStates().elementAt(0).getExeTime();
483 exeTime = cNode.getScheduleNode().getExeTime() - exeTime;
487 private ScheduleNode splitSNode(ScheduleEdge se, boolean copy) {
488 FEdge fe = se.getFEdge();
489 FlagState fs = (FlagState)fe.getTarget();
490 FlagState nfs = (FlagState)fs.clone();
491 fs.getEdgeVector().removeAllElements();
492 nfs.getInedgeVector().removeAllElements();
493 ClassNode sCNode = se.getSourceCNode();
495 // split the subtree whose root is nfs from the whole flag transition tree
496 Vector<FlagState> sfss = sCNode.getFlagStates();
497 Vector<FlagState> fStates = new Vector<FlagState>();
498 Queue<FlagState> toiterate = new LinkedList<FlagState>();
501 while(!toiterate.isEmpty()){
502 FlagState tfs = toiterate.poll();
503 Iterator it_edges = tfs.edges();
504 while(it_edges.hasNext()) {
505 FlagState temp = (FlagState)((FEdge)it_edges.next()).getTarget();
506 if(!fStates.contains(temp)) {
509 sfss.removeElement(temp);
514 Vector<FlagState> sFStates = FlagState.DFS.topology(fStates, null);
516 // create a ClassNode and ScheduleNode for this subtree
517 ClassNode cNode = new ClassNode(sCNode.getClassDescriptor(), sFStates);
518 ScheduleNode sNode = new ScheduleNode(cNode, 0);
519 cNode.setScheduleNode(sNode);
520 cNode.setSorted(true);
521 cNode.setTransTime(sCNode.getTransTime());
522 classNodes.add(cNode);
523 scheduleNodes.add(sNode);
526 } catch (Exception e) {
529 // flush the exeTime of fs and its ancestors
532 while(!toiterate.isEmpty()) {
533 FlagState tfs = toiterate.poll();
534 int ttime = tfs.getExeTime();
535 Iterator it_inedges = tfs.inedges();
536 while(it_inedges.hasNext()) {
537 FEdge fEdge = (FEdge)it_inedges.next();
538 FlagState temp = (FlagState)fEdge.getSource();
539 int time = fEdge.getExeTime() + ttime;
540 if(temp.getExeTime() > time) {
541 temp.setExeTime(time);
548 // create a 'trans' ScheudleEdge between this new ScheduleNode and se's source ScheduleNode
549 ScheduleEdge sEdge = new ScheduleEdge(sNode, "transmit", cNode.getClassDescriptor(), false, 0);
550 sEdge.setTargetFState(fs);
552 sEdge.setSourceCNode(sCNode);
553 sEdge.setTargetCNode(cNode);
554 sEdge.setTargetFState(nfs);
556 // Add calculation codes for calculating transmit time of an object
557 sEdge.setTransTime(cNode.getTransTime());
558 se.getSource().addEdge(sEdge);
559 scheduleEdges.add(sEdge);
560 // redirect ScheudleEdges out of this subtree to the new ScheduleNode
561 Iterator it_sEdges = se.getSource().edges();
562 Vector<ScheduleEdge> toremove = new Vector<ScheduleEdge>();
563 while(it_sEdges.hasNext()) {
564 ScheduleEdge tse = (ScheduleEdge)it_sEdges.next();
565 if((tse != se) && (tse != sEdge) && (tse.getSourceCNode() == sCNode)) {
566 if((tse.getSourceFState() != fs) && (sFStates.contains(tse.getSourceFState()))) {
567 tse.setSource(sNode);
568 tse.setSourceCNode(cNode);
569 sNode.getEdgeVector().addElement(tse);
574 se.getSource().getEdgeVector().removeAll(toremove);
579 //merge se into its source ScheduleNode
580 ((ScheduleNode)se.getSource()).mergeSEdge(se);
581 scheduleNodes.remove(se.getTarget());
582 scheduleEdges.removeElement(se);
583 // As se has been changed into an internal edge inside a ScheduleNode,
584 // change the source and target of se from original ScheduleNodes into ClassNodes.
585 se.setTarget(se.getTargetCNode());
586 se.setSource(se.getSourceCNode());
588 handleScheduleEdge(se, true);
594 public void schedule() throws Exception {
595 if(this.coreNum == -1) {
596 throw new Exception("Error: un-initialized coreNum when doing scheduling.");
599 if(this.schedules == null) {
600 this.schedules = new Vector<Vector<ScheduleNode>>();
603 int reduceNum = this.scheduleNodes.size() - this.coreNum;
605 // Enough cores, no need to merge more ScheduleEdge
606 if(!(reduceNum > 0)) {
607 this.schedules.addElement(this.scheduleNodes);
609 // sort the ScheduleEdges in dececending order of transmittime
610 Vector<ScheduleEdge> sEdges = new Vector<ScheduleEdge>();
611 sEdges.addElement(this.scheduleEdges.elementAt(0));
612 for(int i = 1; i < this.scheduleEdges.size(); i++) {
613 ScheduleEdge temp = this.scheduleEdges.elementAt(i);
614 int j = sEdges.size() - 1;
616 if(temp.getTransTime() > sEdges.elementAt(j--).getTransTime()) {
620 sEdges.add(j+1, temp);
623 int temp = sEdges.elementAt(reduceNum - 1).getTransTime();
624 for(int i = sEdges.size() - 1; i > reduceNum - 1; i--) {
625 if(sEdges.elementAt(i).getTransTime() != temp) {
626 sEdges.removeElementAt(i);
631 int start = reduceNum - 2;
632 for(; start >= 0; start--) {
633 if(sEdges.elementAt(start).getTransTime() != temp) {
643 // generate scheduling
644 Vector candidates = new Vector();
645 for(int i = start; i < sEdges.size(); i++) {
646 candidates.addElement(Integer.valueOf(i));
648 Combination combGen = new Combination(candidates, reduceNum);
651 Vector toreduce = combGen.next();
652 if(toreduce != null) {
653 Vector<ScheduleEdge> reduceEdges = new Vector<ScheduleEdge>();
654 for(int i = 0; i < start; i++) {
655 reduceEdges.add(sEdges.elementAt(i));
657 for(int i = 0; i < toreduce.size(); i++) {
658 reduceEdges.add(sEdges.elementAt(((Integer)toreduce.elementAt(i)).intValue()));
660 Vector<ScheduleNode> sNodes = generateScheduling(reduceEdges, gid++);
661 this.schedules.add(sNodes);
673 // Assign a core to each ScheduleNode
676 for(i = 0; i < scheduleNodes.size(); i++) {
677 ScheduleNode sn = scheduleNodes.elementAt(i);
678 sn.setCoreNum(coreNum++);
680 // For each of the ScheduleEdge out of this ScheduleNode, add the target ScheduleNode into the queue inside sn
681 Iterator it_edges = sn.edges();
682 while(it_edges.hasNext()) {
683 ScheduleEdge se = (ScheduleEdge)it_edges.next();
684 ScheduleNode target = (ScheduleNode)se.getTarget();
685 sn.addTargetSNode(se.getTargetFState().getClassDescriptor(), target);
692 public Vector<ScheduleNode> generateScheduling(Vector<ScheduleEdge> reduceEdges, int gid) {
693 Vector<ScheduleNode> result = new Vector<ScheduleNode>();
695 // clone the ScheduleNodes
696 Hashtable<ScheduleNode, Hashtable<ClassNode, ClassNode>> sn2hash = new Hashtable<ScheduleNode, Hashtable<ClassNode, ClassNode>>();
697 Hashtable<ScheduleNode, ScheduleNode> sn2sn = new Hashtable<ScheduleNode, ScheduleNode>();
698 for(int i = 0; i < this.scheduleNodes.size(); i++) {
699 Hashtable<ClassNode, ClassNode> cn2cn = new Hashtable<ClassNode, ClassNode>();
700 ScheduleNode tocopy = this.scheduleNodes.elementAt(i);
701 ScheduleNode temp = (ScheduleNode)tocopy.clone(cn2cn, gid);
703 sn2hash.put(temp, cn2cn);
704 sn2sn.put(tocopy, temp);
707 // clone the ScheduleEdges and merge those in reduceEdges at the same time
708 Vector<ScheduleEdge> toMerge = new Vector<ScheduleEdge>();
709 for(int i = 0; i < this.scheduleEdges.size(); i++) {
710 ScheduleEdge sse = this.scheduleEdges.elementAt(i);
711 ScheduleNode csource = sn2sn.get(sse.getSource());
712 ScheduleNode ctarget = sn2sn.get(sse.getTarget());
713 Hashtable<ClassNode, ClassNode> sourcecn2cn = sn2hash.get(csource);
714 Hashtable<ClassNode, ClassNode> targetcn2cn = sn2hash.get(ctarget);
717 se = new ScheduleEdge(ctarget, "new", sse.getClassDescriptor(), sse.getIsNew(), gid);
718 se.setProbability(sse.getProbability());
719 se.setNewRate(sse.getNewRate());
720 se.setFEdge(sse.getFEdge());
722 se = new ScheduleEdge(ctarget, "transmit", sse.getClassDescriptor(), false, gid);
724 se.setSourceCNode(sourcecn2cn.get(sse.getSourceCNode()));
725 se.setTargetCNode(targetcn2cn.get(sse.getTargetCNode()));
727 if(reduceEdges.contains(sse)) {
736 for(int i = 0; i < toMerge.size(); i++) {
737 ScheduleEdge sEdge = toMerge.elementAt(i);
739 ((ScheduleNode)sEdge.getSource()).mergeSEdge(sEdge);
740 result.removeElement(sEdge.getTarget());
741 // As se has been changed into an internal edge inside a ScheduleNode,
742 // change the source and target of se from original ScheduleNodes into ClassNodes.
743 sEdge.setTarget(sEdge.getTargetCNode());
744 sEdge.setSource(sEdge.getSourceCNode());
748 String path = "scheduling_" + gid + ".dot";
749 printScheduleGraph(path, result);
754 public void printScheduleGraph(String path, Vector<ScheduleNode> sNodes) {
756 File file=new File(path);
757 FileOutputStream dotstream=new FileOutputStream(file,false);
758 PrintWriter output = new java.io.PrintWriter(dotstream, true);
759 output.println("digraph G {");
760 output.println("\tcompound=true;\n");
761 traverseSNodes(output, sNodes);
762 output.println("}\n");
763 } catch (Exception e) {
769 private void traverseSNodes(PrintWriter output, Vector<ScheduleNode> sNodes){
770 //Draw clusters representing ScheduleNodes
771 Iterator it = sNodes.iterator();
772 while (it.hasNext()) {
773 ScheduleNode gn = (ScheduleNode) it.next();
774 Iterator edges = gn.edges();
775 output.println("\tsubgraph " + gn.getLabel() + "{");
776 output.println("\t\tlabel=\"" + gn.getTextLabel() + "\";");
777 Iterator it_cnodes = gn.getClassNodesIterator();
778 traverseCNodes(output, it_cnodes);
779 //Draw the internal 'new' edges
780 Iterator it_edges =gn.getScheduleEdgesIterator();
781 while(it_edges.hasNext()) {
782 ScheduleEdge se = (ScheduleEdge)it_edges.next();
784 if(se.getSourceCNode().isclone()) {
785 output.print(se.getSourceCNode().getLabel());
787 if(se.getSourceFState() == null) {
788 output.print(se.getSourceCNode().getClusterLabel());
790 output.print(se.getSourceFState().getLabel());
794 output.print(" -> ");
795 if(se.getTargetFState() == null) {
796 if(se.getTargetCNode().isclone()) {
797 output.print(se.getTargetCNode().getLabel());
799 output.print(se.getTargetCNode().getClusterLabel());
801 output.println(" [label=\"" + se.getLabel() + "\", color=red];");
803 output.print(se.getTargetFState().getLabel() + " [label=\"" + se.getLabel() + "\", color=red, ltail=");
804 if(se.getSourceCNode().isclone()) {
805 output.println(se.getSourceCNode().getLabel() + "];");
807 output.println(se.getSourceCNode().getClusterLabel() + "];");
811 output.println("\t}\n");
812 //Draw 'new' edges of this ScheduleNode
813 while(edges.hasNext()) {
814 ScheduleEdge se = (ScheduleEdge)edges.next();
816 if(se.getSourceCNode().isclone()) {
817 output.print(se.getSourceCNode().getLabel());
819 if(se.getSourceFState() == null) {
820 output.print(se.getSourceCNode().getClusterLabel());
822 output.print(se.getSourceFState().getLabel());
826 output.print(" -> ");
827 if(se.getTargetFState() == null) {
828 if(se.getTargetCNode().isclone()) {
829 output.print(se.getTargetCNode().getLabel());
831 output.print(se.getTargetCNode().getClusterLabel());
833 output.println(" [label=\"" + se.getLabel() + "\", color=red, style=dashed]");
835 output.println(se.getTargetFState().getLabel() + " [label=\"" + se.getLabel() + "\", color=red, style=dashed]");
841 private void traverseCNodes(PrintWriter output, Iterator it){
842 //Draw clusters representing ClassNodes
843 while (it.hasNext()) {
844 ClassNode gn = (ClassNode) it.next();
846 output.println("\t\t" + gn.getLabel() + " [style=dashed, label=\"" + gn.getTextLabel() + "\", shape=box];");
848 output.println("\tsubgraph " + gn.getClusterLabel() + "{");
849 output.println("\t\tstyle=dashed;");
850 output.println("\t\tlabel=\"" + gn.getTextLabel() + "\";");
851 traverseFlagStates(output, gn.getFlagStates());
852 output.println("\t}\n");
857 private void traverseFlagStates(PrintWriter output, Collection nodes) {
858 Set cycleset=GraphNode.findcycles(nodes);
859 Vector namers=new Vector();
860 namers.add(new Namer());
861 namers.add(new Allocations());
862 //namers.add(new TaskEdges());
864 Iterator it = nodes.iterator();
865 while (it.hasNext()) {
866 GraphNode gn = (GraphNode) it.next();
867 Iterator edges = gn.edges();
869 String dotnodeparams="";
871 for(int i=0;i<namers.size();i++) {
872 Namer name=(Namer) namers.get(i);
873 String newlabel=name.nodeLabel(gn);
874 String newparams=name.nodeOption(gn);
876 if (!newlabel.equals("") && !label.equals("")) {
879 if (!newparams.equals("")) {
880 dotnodeparams+=", " + name.nodeOption(gn);
882 label+=name.nodeLabel(gn);
884 label += ":[" + ((FlagState)gn).getExeTime() + "]";
887 output.println("\t" + gn.getLabel() + " [label=\"" + label + "\"" + dotnodeparams + "];");
890 while (edges.hasNext()) {
891 Edge edge = (Edge) edges.next();
892 GraphNode node = edge.getTarget();
893 if (nodes.contains(node)) {
894 for(Iterator nodeit=nonmerge(node, nodes).iterator();nodeit.hasNext();) {
895 GraphNode node2=(GraphNode)nodeit.next();
896 String edgelabel = "";
897 String edgedotnodeparams="";
899 for(int i=0;i<namers.size();i++) {
900 Namer name=(Namer) namers.get(i);
901 String newlabel=name.edgeLabel(edge);
902 String newoption=name.edgeOption(edge);
903 if (!newlabel.equals("")&& ! edgelabel.equals(""))
906 if (!newoption.equals(""))
907 edgedotnodeparams+=", "+newoption;
909 edgelabel+=":[" + ((FEdge)edge).getExeTime() + "]";
910 Hashtable<ClassDescriptor, NewObjInfo> hashtable = ((FEdge)edge).getNewObjInfoHashtable();
911 if(hashtable != null) {
912 Set<ClassDescriptor> keys = hashtable.keySet();
913 Iterator it_keys = keys.iterator();
914 while(it_keys.hasNext()) {
915 ClassDescriptor cd = (ClassDescriptor)it_keys.next();
916 NewObjInfo noi = hashtable.get(cd);
917 edgelabel += ":{ class " + cd.getSymbol() + " | " + noi.getNewRate() + " | (" + noi.getProbability() + "%) }";
920 output.println("\t" + gn.getLabel() + " -> " + node2.getLabel() + " [" + "label=\"" + edgelabel + "\"" + edgedotnodeparams + "];");
927 private Set nonmerge(GraphNode gn, Collection nodes) {
928 HashSet newset=new HashSet();
929 HashSet toprocess=new HashSet();
931 while(!toprocess.isEmpty()) {
932 GraphNode gn2=(GraphNode)toprocess.iterator().next();
933 toprocess.remove(gn2);
937 Iterator edges = gn2.edges();
938 while (edges.hasNext()) {
939 Edge edge = (Edge) edges.next();
940 GraphNode node = edge.getTarget();
941 if (!newset.contains(node)&&nodes.contains(node))
956 public Combination(Vector factors, int selectNum) throws Exception{
957 this.factors = factors;
958 if(factors.size() < selectNum) {
959 throw new Exception("Error: selectNum > candidates' number in combination.");
961 if(factors.size() == selectNum) {
967 this.head = this.factors.remove(0);
969 this.resultNum = this.factors.size() + 1;
973 this.tail = new Combination((Vector)this.factors.clone(), selectNum - 1);
974 this.selectNum = selectNum;
976 for(int i = factors.size(); i > selectNum; i--) {
979 for(int i = factors.size() - selectNum; i > 0; i--) {
984 public Vector next() {
990 Vector result = this.factors;
993 if(this.tail == null) {
995 Vector result = new Vector();
996 result.add(this.head);
998 this.head = this.factors.remove(0);
1002 Vector result = this.tail.next();
1003 if(result == null) {
1004 if(this.factors.size() == this.selectNum) {
1007 result = this.factors;
1011 this.head = this.factors.remove(0);
1013 this.tail = new Combination((Vector)this.factors.clone(), selectNum - 1);
1014 result = this.tail.next();
1015 } catch(Exception e) {
1016 e.printStackTrace();
1020 result.add(0, head);