AssignmentProblem.java

/**
 * Copyright (c) 2004-2025 Carnegie Mellon University and others. (see Contributors file).
 * All Rights Reserved.
 *
 * NO WARRANTY. ALL MATERIAL IS FURNISHED ON AN "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY
 * KIND, EITHER EXPRESSED OR IMPLIED, AS TO ANY MATTER INCLUDING, BUT NOT LIMITED TO, WARRANTY OF FITNESS FOR PURPOSE
 * OR MERCHANTABILITY, EXCLUSIVITY, OR RESULTS OBTAINED FROM USE OF THE MATERIAL. CARNEGIE MELLON UNIVERSITY DOES NOT
 * MAKE ANY WARRANTY OF ANY KIND WITH RESPECT TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.
 *
 * This program and the accompanying materials are made available under the terms of the Eclipse Public License 2.0
 * which is available at https://www.eclipse.org/legal/epl-2.0/
 * SPDX-License-Identifier: EPL-2.0
 *
 * Created, in part, with funding and support from the United States Government. (see Acknowledgments file).
 *
 * This program includes and/or can make use of certain third party source code, object code, documentation and other
 * files ("Third Party Software"). The Third Party Software that is used by this program is dependent upon your system
 * configuration. By using this program, You agree to comply with any and all relevant Third Party Software terms and
 * conditions contained in any such Third Party Software or separate license file distributed with such Third Party
 * Software. The parties who own the Third Party Software ("Third Party Licensors") are intended third party benefici-
 * aries to this license with respect to the terms applicable to their Third Party Software. Third Party Software li-
 * censes only apply to the Third Party Software and not any other portion of this program or this program as a whole.
 */
package EAnalysis.BinPacking;

import java.io.PrintWriter;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.Vector;

public class AssignmentProblem implements Cloneable {

	BPErrorReporter errorReporter;

	public void setErrorReporter(BPErrorReporter r) {
		errorReporter = r;
	}

	/**
	 * SoftwareNodes set ordered byte non-increasing bandwidth requirement
	 */
	private TreeSet softwareGraph;

	TreeSet nonDeployableModules;

	/**
	 * Connectivity matrix: each row is indexed by software node object. Each
	 * row contains another TreeMap with (key, value) pairs as (message,
	 * software node) ordered by non-increasing bandwidth requirement.
	 */
	TreeMap softwareConnectivity;

	/**
	 * This is a matrix (hashtable of hashtables) to address node-to-node
	 * indexing of the messages. This speeds up the lookup of the messages to a
	 * particular target
	 */
	Hashtable softConnectivityByTarget;

	/**
	 * Hardware nodes ordered byte non-decreasing available bandwidth capacity
	 */
	private TreeSet hardwareGraph;

	/**
	 * Hardware connectivity. Rows indexed byte hardwareNode. Each row contains
	 * another TreeMap with pairs key->value: key in$ link} and value in$
	 * {hardware Node}. These rows are ordered int non-decreasing available
	 * bandwidth capacity
	 */
	TreeMap hardwareConnectivity;

	/**
	 * The constraints is a set of SoftwareNode groups of two types: jointion
	 * and disjointion. Jointion is the set of SoftwareNodes that must be
	 * deployed together. Disjointion is the set of SoftwareNodes that must be
	 * deployed on different nodes. This set will be indexed by node, i.e., each
	 * node will have a pointer to a set of constraints in which it is involved.
	 * This way each time we try to deploy a node we would be able to check the
	 * constraints.
	 */
	Hashtable constraints = new Hashtable();

	Comparator bwComparator;

	Comparator capComparator;

	public AssignmentProblem() {
	}

	public AssignmentProblem(Comparator bwComparator, Comparator capComparator) {
		if (bwComparator == null || capComparator == null) {
			throw new IllegalArgumentException("Comparators are null");
		}

		setHardwareGraph(new TreeSet(capComparator));
		setSoftwareGraph(new TreeSet(bwComparator));
		nonDeployableModules = new TreeSet(bwComparator);
		hardwareConnectivity = new TreeMap(capComparator);
		softwareConnectivity = new TreeMap(bwComparator);
		softConnectivityByTarget = new Hashtable();
		this.bwComparator = bwComparator;
		this.capComparator = capComparator;
	}

	@Override
	public Object clone() {
		AssignmentProblem p = new AssignmentProblem();
		p.setHardwareGraph((TreeSet) getHardwareGraph().clone());
		p.setSoftwareGraph((TreeSet) getSoftwareGraph().clone());
		p.nonDeployableModules = (TreeSet) nonDeployableModules.clone();
		p.hardwareConnectivity = (TreeMap) hardwareConnectivity.clone();
		p.softwareConnectivity = (TreeMap) softwareConnectivity.clone();
		p.softConnectivityByTarget = (Hashtable) softConnectivityByTarget.clone();
		p.constraints = (Hashtable) constraints.clone();
		p.bwComparator = bwComparator;
		p.capComparator = capComparator;
		return p;
	}

	/**
	 * Add a new constraint to the AssignmentProblem. It will merge
	 * SoftwareNodes as necessary to simplify the search.
	 */
	public void addConstraint(Constraint c) {
		if (c instanceof Joint) {
			System.out.println("Adding a Joint");
			/*
			 * Merge the SoftwareNodes into a single composite to ensure that
			 * they are deployed together
			 */
			CompositeSoftNode compNode = new CompositeSoftNode(bwComparator);
			for (int i = 0; i < c.members.size(); i++) {
				compNode.add((SoftwareNode) c.members.elementAt(i), softwareConnectivity, softConnectivityByTarget);
				getSoftwareGraph().remove(c.members.elementAt(i));
				Vector v = (Vector) constraints.get(c.members.get(i));
				if (v == null) {
					v = new Vector();
					constraints.put(c.members.get(i), v);
				}
				if (v.size() != 0) {
					for (int j = 0; j < v.size(); j++) {
						if (v.get(j) instanceof Joint) {
							Joint joint = (Joint) v.get(j);
							for (int k = 0; k < joint.members.size(); k++) {
								compNode.add((SoftwareNode) joint.members.get(k), softwareConnectivity,
										softConnectivityByTarget);
							}
							getSoftwareGraph().remove(joint.getCompositeNode());
							// TODO do I need to remove the old joint
							// constraint?
						} else if (v.get(j) instanceof Disjoint) {
							((Disjoint) v.get(j)).add(compNode);
						}
					}
				}
				v.add(c);
			}
			compNode.breakable = false;
			getSoftwareGraph().add(compNode);
			((Joint) c).setCompositeNode(compNode);
		} else if (c.members.size() > 0) // Disjoint or Isolation
		{
			System.out.print("Adding a disjoint members [");
			for (int i = 0; i < c.members.size(); i++) {
				SoftwareNode n = (SoftwareNode) c.members.get(i);
				System.out.print(n.getSemanticObject());
			}
			System.out.println("]");
			for (int i = 0; i < c.members.size(); i++) {
				Vector v = (Vector) constraints.get(c.members.get(i));
				System.out.println("\t got constaint Vector v(" + v + ") [0] = "
						+ ((v != null && v.size() > 0) ? v.get(0).toString() : "null"));
				if (v == null) {
					v = new Vector();
					constraints.put(c.members.get(i), v);
				}
				if (v.size() != 0) {
					for (int j = 0; j < v.size(); j++) {
						if (v.get(j) instanceof Joint) {
							System.out.println("\t Recursively adding a Joint to the disjoint");
							c.add(((Joint) v.get(j)).getCompositeNode());
						}
					}
				}
				v.add(c);
			}
		}
	}

	/**
	 * Add the
	 *
	 * @param link
	 *            to the hardware connectivity matrix
	 */
	public void addLink(Link link) {
		for (Iterator iter = link.getConnectedNodes().iterator(); iter.hasNext();) {
			HardwareNode node = (HardwareNode) iter.next();
			TreeSet connectivitySet = (TreeSet) hardwareConnectivity.remove(node);
			if (connectivitySet == null) {
				connectivitySet = new TreeSet(capComparator);
				// DebugMonitor.println(DebugMonitor.channels[1],"ADDED
				// CONNECTIVITY: LINK("+link.toString()+")
				// PROC("+node.toString()+")");
			}
			if (!connectivitySet.contains(link)) {
				connectivitySet.add(link);
			}
			hardwareConnectivity.put(node, connectivitySet);
		}
	}

	public void removeLink(Link link) {
		for (Iterator iter = link.getConnectedNodes().iterator(); iter.hasNext();) {
			HardwareNode node = (HardwareNode) iter.next();
			TreeSet connectivitySet = (TreeSet) hardwareConnectivity.remove(node);
			if (connectivitySet != null) {
				connectivitySet.remove(link);
				// if (!connectivitySet.remove(link))
				// DebugMonitor.println(DebugMonitor.channels[1],"WARNING --
				// could not remove link("+link.toString()+") from
				// node("+node.toString()+")");
				hardwareConnectivity.put(node, connectivitySet);
			} else {
				// DebugMonitor.println(DebugMonitor.channels[1],"REMOVE LINK
				// ERROR: LINK("+link.toString()+") PROC("+node.toString()+")
				// w/o connectivity");
			}
		}
	}

	public Link getConnectingLink(HardwareNode n1, HardwareNode n2) {
		TreeSet cs = (TreeSet) hardwareConnectivity.get(n1);
		if (cs == null) {
			return null;
		}

		for (Iterator iter = cs.iterator(); iter.hasNext();) {
			Link l = (Link) iter.next();
			if (l.getConnectedNodes().contains(n2)) {
				return l;
			}
		}
		return null;
	}

	/**
	 * Add the message
	 *
	 * @param m
	 *            to the software connectivity matrix. FIXME: we should use
	 *            multicast messages similar to links in hardware.
	 */
	public void addMessage(Message m) {
		TreeMap sConnVector = (TreeMap) softwareConnectivity.get(m.getSender());
		Hashtable sConnVectorByTarget = (Hashtable) softConnectivityByTarget.get(m.getSender());
		TreeMap rConnVector = (TreeMap) softwareConnectivity.get(m.getReceiver());
		Hashtable rConnVectorByTarget = (Hashtable) softConnectivityByTarget.get(m.getReceiver());

		if (sConnVector == null) {
			sConnVector = new TreeMap(bwComparator);
			softwareConnectivity.put(m.getSender(), sConnVector);
		}
		if (rConnVector == null) {
			rConnVector = new TreeMap(bwComparator);
			softwareConnectivity.put(m.getReceiver(), rConnVector);
		}
		if (sConnVectorByTarget == null) {
			sConnVectorByTarget = new Hashtable();
			softConnectivityByTarget.put(m.getSender(), sConnVectorByTarget);
		}
		if (rConnVectorByTarget == null) {
			rConnVectorByTarget = new Hashtable();
			softConnectivityByTarget.put(m.getReceiver(), rConnVectorByTarget);
		}
		sConnVector.put(m, m.getReceiver());
		rConnVector.put(m, m.getSender());

		sConnVectorByTarget.put(m.getReceiver(), m);
		rConnVectorByTarget.put(m.getSender(), m);
	}

	/**
	 * get the processors that do not conflict with the module.
	 */
	public TreeSet getValidProcessorsForModule(SoftwareNode n) {
		TreeSet set = null;

		/* check if */
		Vector v = (Vector) constraints.get(n);
		if (v != null) {
			set = (TreeSet) getHardwareGraph().clone();
			int vSize = v.size();
			for (int i = 0; i < vSize; i++) {
				Constraint c = (Constraint) v.get(i);
				if (c instanceof SetConstraint) {
					SetConstraint sc = (SetConstraint) c;
					for (Iterator iter = set.iterator(); iter.hasNext();) {
						HardwareNode hn = (HardwareNode) iter.next();
						boolean belongs = false;
						for (int j = 0; j < sc.hardwareMembers.size(); j++) {
							Object o = sc.hardwareMembers.get(j);
							if (o instanceof Class) {
								Class clazz = (Class) o;
								if (clazz.isInstance(hn)) {
									belongs = true;
									break;
								}
							} else {
								if (o.equals(hn)) {
									belongs = true;
									break;
								}
							}
						}
						if (!belongs) {
							iter.remove();
						}
					}
				} else if (c instanceof Disjoint) {
					int cSize = c.members.size();
					for (int j = 0; j < cSize; j++) {
						SoftwareNode other = (SoftwareNode) c.members.get(j);
						if (other instanceof CompositeSoftNode) {
							TreeSet basicNodes = ((CompositeSoftNode) other).getBasicComponents();
							for (Iterator iter = basicNodes.iterator(); iter.hasNext();) {
								SoftwareNode elem = (SoftwareNode) iter.next();
								HardwareNode hn = elem.getDeployedTo();
								/* remove where the other is deployed */
								if (hn != null) {
									set.remove(hn);
								}
							}
						} else {
							HardwareNode hn = other.getDeployedTo();
							/* remove where the other is deployed */
							if (hn != null) {
								set.remove(hn);
							}
						}
					}
				}
			}
			return set;
		}
		return (set != null) ? set : getHardwareGraph();
	}

	public int dumpHardwareText(PrintWriter writer, int initialNodeID, int initY, boolean printGraphHeader) {
		int nextNodeID = initialNodeID;
		Hashtable nodeToID = new Hashtable();
		HashSet printedLinks = new HashSet();
		String tabs = "";

		int nodeYposition = initY;
		int nextLinkID = nextNodeID;

		for (Iterator iter = getHardwareGraph().iterator(); iter.hasNext();) {
			HardwareNode node = (HardwareNode) iter.next();
			Integer nodeInt = (Integer) nodeToID.get(node);
			if (nodeInt == null) {
				nodeInt = new Integer(nextNodeID++);
				nodeToID.put(node, nodeInt);
			}
			int nodeID = nodeInt.intValue();
			writer.println("node[" + nodeID + "]C(" + node.getAvailableCapacity() + ")");

			TreeSet connSet = (TreeSet) hardwareConnectivity.get(node);
			if (connSet != null) {
				for (Iterator links = connSet.iterator(); links.hasNext();) {
					Link link = (Link) links.next();

					/* avoid double printing */
					if (!printedLinks.contains(link)) {
						int linkID = nextLinkID++;
						// printedLinks.add(link);
						writer.println("\t link[" + linkID + "]BW(" + link.getAvailableCapacity() + " bits/s)");

						for (Iterator conNodes = link.getConnectedNodes().iterator(); conNodes.hasNext();) {
							HardwareNode conNode = (HardwareNode) conNodes.next();
							Integer conNodeInteger = (Integer) nodeToID.get(conNode);
							int conNodeID;
							if (conNodeInteger == null) {
								conNodeID = nextNodeID++;
								conNodeInteger = new Integer(conNodeID);
								nodeToID.put(conNode, conNodeInteger);
							}
							conNodeID = ((Integer) nodeToID.get(conNode)).intValue();
							writer.println("\t\t node [" + conNodeID + "]");
						}
					}
				}
			}
		}

		if (printGraphHeader) {
			writer.println("]");
		}

		return nextLinkID;
	}

	/**
	 * dumps the hardware graph into a GML stream (e.g. file) and returns the
	 * smallest node id unused.
	 */
	public int dumpHardwareGML(PrintWriter writer, int initialNodeID, int initY, boolean printGraphHeader) {
		int nextNodeID = initialNodeID;
		Hashtable nodeToID = new Hashtable();
		HashSet printedLinks = new HashSet();
		String tabs = "";
		if (printGraphHeader) {
			writer.println("graph[");
			writer.println("directed 0");
		}

		int nodeYposition = initY;
		for (Iterator iter = getHardwareGraph().iterator(); iter.hasNext();) {
			HardwareNode node = (HardwareNode) iter.next();
			Integer nodeInt = (Integer) nodeToID.get(node);
			if (nodeInt == null) {
				nodeInt = new Integer(nextNodeID++);
				nodeToID.put(node, nodeInt);
			}
			int nodeID = nodeInt.intValue();

			writer.println("\t node [");
			writer.println("\t\t id " + nodeID);

			String taskList = "";

			for (Iterator iter1 = node.getTaskSet().iterator(); iter1.hasNext();) {
				ProcessingLoad l = (ProcessingLoad) iter1.next();
				taskList += l.getName();
			}

			writer.println("\t\t label \"" + node.getName() + ":" + taskList + ":" + node.getCyclesPerSecond() + " cycles/s\"");
			writer.println("\t\t graphics [");
			writer.println("\t\t\t Image [");
			writer.println("\t\t\t\t Type \"URL\"");
			writer.println("\t\t\t\t Location \"\"");
			writer.println("\t\t\t ]");
			writer.println("\t\t\t center [");
			writer.println("\t\t\t\t x 100.0");
			writer.println("\t\t\t\t y " + nodeYposition + ".0");
			nodeYposition += 50;
			writer.println("\t\t\t\t z 0.0");
			writer.println("\t\t\t ]");
			writer.println("\t\t\t width 20.0");
			writer.println("\t\t\t height 20.0");
			writer.println("\t\t\t depth 20.0");
			writer.println("\t\t ]");
			writer.println("\t\t vgj [");
			writer.println("\t\t\t labelPosition \"below\"");
			writer.println("\t\t\t shape \"Rectangle\"");
			writer.println("\t\t ]");
			writer.println("\t ]");
		}

		int nextLinkID = nextNodeID;

		for (Iterator iter = getHardwareGraph().iterator(); iter.hasNext();) {
			HardwareNode node = (HardwareNode) iter.next();
			int nodeID = ((Integer) nodeToID.get(node)).intValue();
			TreeSet connSet = (TreeSet) hardwareConnectivity.get(node);
			for (Iterator links = connSet.iterator(); links.hasNext();) {
				Link link = (Link) links.next();

				/* avoid double printing */
				if (!printedLinks.contains(link)) {
					int linkID = nextLinkID++;
					printedLinks.add(link);
					writer.println("\t node [");
					writer.println("\t\t id " + linkID);
					writer.println("\t\t label \"" + link.getName() + ":" + link.getCyclesPerSecond() + " bits/s\"");
					writer.println("\t\t graphics [");
					writer.println("\t\t\t Image [");
					writer.println("\t\t\t\t Type \"URL\"");
					writer.println("\t\t\t\t Location \"\"");
					writer.println("\t\t\t ]");
					writer.println("\t\t\t center [");
					writer.println("\t\t\t\t x 100.0");
					writer.println("\t\t\t\t y " + nodeYposition + ".0");
					nodeYposition += 50;
					writer.println("\t\t\t\t z 0.0");
					writer.println("\t\t\t ]");
					writer.println("\t\t\t width 30.0");
					writer.println("\t\t\t height 10.0");
					writer.println("\t\t\t depth 10.0");
					writer.println("\t\t ]");
					writer.println("\t\t vgj [");
					writer.println("\t\t\t labelPosition \"below\"");
					writer.println("\t\t\t shape \"Rectangle\"");
					writer.println("\t\t ]");
					writer.println("\t ]");

					for (Iterator conNodes = link.getConnectedNodes().iterator(); conNodes.hasNext();) {
						HardwareNode conNode = (HardwareNode) conNodes.next();
						int conNodeID = ((Integer) nodeToID.get(conNode)).intValue();
						writer.println("\t edge [");
						writer.println("\t\t linestyle \"solid\"");
						writer.println("\t\t label \"\"");
						writer.println("\t\t source " + linkID);
						writer.println("\t\t target " + conNodeID);
						writer.println("\t ]");
					}
				}
			}
		}

		if (printGraphHeader) {
			writer.println("]");
		}

		return nextLinkID;
	}

	/**
	 * dumps the software graph to GML stream (e.g. file) and returns the
	 * smallest node id unused
	 */
	public int dumpSoftwareGML(PrintWriter writer, int initialNodeID, int initY, boolean printGraphHeader) {
		return dumpSoftGraphGML(getSoftwareGraph(), writer, initialNodeID, initY, printGraphHeader);
	}

	public int dumpNonDeployableGML(PrintWriter writer, int initialNodeID, int initY, boolean printGraphHeader) {
		return dumpSoftGraphGML(nonDeployableModules, writer, initialNodeID, initY, printGraphHeader);
	}

	public int dumpSoftGraphGML(TreeSet softGraph, PrintWriter writer, int initialNodeID, int initY,
			boolean printGraphHeader) {
		int nextNodeID = initialNodeID;
		Hashtable nodeToID = new Hashtable();
		HashSet printedLinks = new HashSet();

		if (printGraphHeader) {
			writer.println("graph[");
			writer.println("directed 0");
		}

		int nodeYposition = initY;
		for (Iterator iter = softGraph.iterator(); iter.hasNext();) {
			SoftwareNode node = (SoftwareNode) iter.next();
			Integer nodeInt = (Integer) nodeToID.get(node);
			if (nodeInt == null) {
				nodeInt = new Integer(nextNodeID++);
				nodeToID.put(node, nodeInt);
			}
			int nodeID = nodeInt.intValue();

			writer.println("\t node [");
			writer.println("\t\t id " + nodeID);
			writer.println(
					"\t\t label \"" + node.name + ": BW(" + node.getBandwidth() + " cycle/s), C(" + node.getCycles()
							+ " cycles), T(" + node.getPeriod() + " nanos), D(" + node.getDeadline() + " nanos)\"");
			writer.println("\t\t graphics [");
			writer.println("\t\t\t Image [");
			writer.println("\t\t\t\t Type \"URL\"");
			writer.println("\t\t\t\t Location \"\"");
			writer.println("\t\t\t ]");
			writer.println("\t\t\t center [");
			writer.println("\t\t\t\t x 100.0");
			writer.println("\t\t\t\t y " + nodeYposition + ".0");
			nodeYposition += 50;
			writer.println("\t\t\t\t z 0.0");
			writer.println("\t\t\t ]");
			writer.println("\t\t\t width 20.0");
			writer.println("\t\t\t height 20.0");
			writer.println("\t\t\t depth 20.0");
			writer.println("\t\t ]");
			writer.println("\t\t vgj [");
			writer.println("\t\t\t labelPosition \"below\"");
			writer.println("\t\t\t shape \"Oval\"");
			writer.println("\t\t ]");
			writer.println("\t ]");
		}

		Vector printedMessages = new Vector();
		for (Iterator iter = softGraph.iterator(); iter.hasNext();) {
			SoftwareNode node = (SoftwareNode) iter.next();
			int nodeID = ((Integer) nodeToID.get(node)).intValue();
			TreeMap connSet = (TreeMap) softwareConnectivity.get(node);
			if (connSet != null) {
				for (Iterator messages = connSet.keySet().iterator(); messages.hasNext();) {
					Message msg = (Message) messages.next();
					System.out.println("dumping msg(" + node.getName() + "," + msg.getPartner(node).getName() + ")");
					int partnerID = 0;
					try {
						partnerID = ((Integer) nodeToID.get(msg.getPartner(node))).intValue();
					} catch (Exception e) {
						System.out.println(msg.getPartner(node).name);
					}

					String msgID = Integer.toString((nodeID > partnerID) ? nodeID : partnerID)
							+ Integer.toString((nodeID < partnerID) ? nodeID : partnerID);
					if (printedMessages.contains(msgID)) {
						continue;
					}

					printedMessages.add(msgID);

					writer.println("\t edge [");
					writer.println("\t\t linestyle \"solid\"");
					writer.println("\t\t label \"C(" + msg.getCycles() + "),T(" + msg.getPeriod() + "),D("
							+ msg.getDeadline() + ")\"");
					writer.println("\t\t source " + nodeID);
					writer.println("\t\t target " + partnerID);
					writer.println("\t ]");

				}
			}
		}

		if (printGraphHeader) {
			writer.println("]");
		}

		return nextNodeID;
	}

	public int dumpSoftGraphText(TreeSet softGraph, PrintWriter writer, int initialNodeID, int initY,
			boolean printGraphHeader) {
		int nextNodeID = initialNodeID;
		int nextMsgID = 0;
		Hashtable nodeToID = new Hashtable();
		HashSet printedLinks = new HashSet();

		int nodeYposition = initY;

		for (Iterator iter = softGraph.iterator(); iter.hasNext();) {
			SoftwareNode node = (SoftwareNode) iter.next();
			Integer nodeInt = (Integer) nodeToID.get(node);
			if (nodeInt == null) {
				nodeInt = new Integer(nextNodeID++);
				nodeToID.put(node, nodeInt);
			}
			int nodeID = nodeInt.intValue();

			writer.println(" software node(" + node + ") [" + nodeID + ",name(" + node.name + ")]: BW("
					+ node.getBandwidth() + "), C(" + node.getCycles() + "), T(" + node.getPeriod() + "), D("
					+ node.getDeadline() + ")");

			TreeMap connSet = (TreeMap) softwareConnectivity.get(node);
			if (connSet != null) {
				for (Iterator messages = connSet.keySet().iterator(); messages.hasNext();) {
					Message msg = (Message) messages.next();
					SoftwareNode other = msg.getPartner(node);
					int partnerID = 0;
					Integer partnerInteger;
					if (msg.getPartner(node) != null) {
						partnerInteger = (Integer) ((msg.getPartner(node) == null) ? null
								: nodeToID.get(msg.getPartner(node)));
						if (partnerInteger == null) {
							partnerID = nextNodeID++;
							partnerInteger = new Integer(partnerID);
							nodeToID.put(msg.getPartner(node), partnerInteger);
						}

						writer.println("\t msg C(" + msg.getCycles() + "),T(" + msg.getPeriod() + "),D("
								+ msg.getDeadline() + ") BW(" + msg.getBandwidth() + ")");
						writer.println("\t\t target " + other.name); // partnerID);
					}
				}
			}
		}
		return nextNodeID;
	}

	/**
	 * @since 3.0
	 */
	public TreeSet getSoftwareGraph() {
		return softwareGraph;
	}

	/**
	 * @since 3.0
	 */
	public void setSoftwareGraph(TreeSet softwareGraph) {
		this.softwareGraph = softwareGraph;
	}

	/**
	 * @since 3.0
	 */
	public TreeSet getHardwareGraph() {
		return hardwareGraph;
	}

	/**
	 * @since 3.0
	 */
	public void setHardwareGraph(TreeSet hardwareGraph) {
		this.hardwareGraph = hardwareGraph;
	}
}