public int testGraphIterators() { int foo = 0; // Iterating on all nodes start = System.currentTimeMillis(); Iterator<Node> nodeIt = g.getNodeIterator(); while (nodeIt.hasNext()) { Node n = nodeIt.next(); if (n.hasAttribute("foo")) foo++; } end = System.currentTimeMillis(); measureValues.put(Measures.GRAPH_NODE_IT, end - start); // iterating on all edges start = System.currentTimeMillis(); Iterator<Edge> edgeIt = g.getEdgeIterator(); while (edgeIt.hasNext()) { Edge e = edgeIt.next(); if (e.hasAttribute("foo")) foo++; } end = System.currentTimeMillis(); measureValues.put(Measures.GRAPH_EDGE_IT, end - start); return foo; }
// For adding Edge To Graph public void AddEdgeToGraph( String First_IP, String Second_IP, String edge_details, boolean IsSwitch_1, boolean IsSwitch_2) { try { String temp_1 = "OpenVSwitch"; String temp_2 = "OpenVSwitch"; if (!IsSwitch_1) { temp_1 = "EndHost"; } if (!IsSwitch_2) { temp_2 = "EndHost"; } String node_name_1 = temp_1 + " [" + First_IP + "]"; String node_name_2 = temp_2 + " [" + Second_IP + "]"; network_graph.addEdge(edge_details, node_name_1, node_name_2); Edge edge = network_graph.getEdge(edge_details); edge.addAttribute("ui.label", edge.getId()); } catch (Exception e) { } }
public void testAddRemove() { // add 10000 new nodes start = System.currentTimeMillis(); for (int i = 0; i < 10000; i++) g.addNode("__newnode__" + i); end = System.currentTimeMillis(); measureValues.put(Measures.ADD_NODE, end - start); // for each new node n, add 100 edges between n and old nodes start = System.currentTimeMillis(); int current = 0; int edgeId = 0; for (int i = 0; i < 10000; i++) { String id = "__newnode__" + i; for (int j = 0; j < 100; j++) { g.addEdge("__newedge__" + edgeId, id, nodeIds.get(current)); edgeId++; current++; if (current == nodeIds.size()) current = 0; } } end = System.currentTimeMillis(); measureValues.put(Measures.ADD_EDGE, end - start); // remove all the new nodes (and new edges) start = System.currentTimeMillis(); for (int i = 0; i < 10000; i++) g.removeNode("__newnode__" + i); end = System.currentTimeMillis(); measureValues.put(Measures.REMOVE_NODE, end - start); // remove 10000 edges start = System.currentTimeMillis(); for (int i = 0; i < 10000; i++) g.removeEdge(edgeIds.get(i)); end = System.currentTimeMillis(); measureValues.put(Measures.REMOVE_EDGE, end - start); }
public int testBfsDfs() { int foo = 0; // BFS from 1000 nodes start = System.currentTimeMillis(); for (int i = 0; i < 1000; i++) { Iterator<Node> bfsIt = g.getNode(nodeIds.get(i)).getBreadthFirstIterator(); while (bfsIt.hasNext()) { Node node = bfsIt.next(); if (node.hasAttribute("foo")) foo++; } } end = System.currentTimeMillis(); measureValues.put(Measures.BFS_IT, end - start); // DFS from 1000 nodes - tested only for new implementations // because of a bug in the old start = System.currentTimeMillis(); if (g instanceof org.graphstream.graph.implementations.AbstractGraph) { for (int i = 0; i < 1000; i++) { Iterator<Node> dfsIt = g.getNode(nodeIds.get(i)).getDepthFirstIterator(); while (dfsIt.hasNext()) { Node node = dfsIt.next(); if (node.hasAttribute("foo")) foo++; } } } end = System.currentTimeMillis(); measureValues.put(Measures.DFS_IT, end - start); return foo; }
public Graph tree2graph(SimpleNode node) { Graph graph = new DefaultGraph("Sample graph"); graph.setStrict(false); graph.addAttribute("ui.stylesheet", style); graph.addNode(node.getId()).addAttribute("label", node.getName()); graph.getNode(node.getId()).addAttribute("ui.class", "root"); this.iterateGraph(node, graph); return graph; }
/** * Merge several graphs in one. The first parameter is the graph in which the other graphs will be * merged. * * @param result destination graph. * @param graphs all graphs that will be merged in result. */ public static void mergeIn(Graph result, Graph... graphs) { boolean strict = result.isStrict(); GraphReplay replay = new GraphReplay(String.format("replay-%x", System.nanoTime())); replay.addSink(result); result.setStrict(false); if (graphs != null) for (Graph g : graphs) replay.replay(g); replay.removeSink(result); result.setStrict(strict); }
public static void main(String args[]) { Graph graph = new SingleGraph("neighborhood"); GeoSource src = new GeoSourceOSM_Neighborhood(0.0003, "/home/merwan/neighborhood.osm"); src.addSink(graph); src.read(); src.end(); graph.display(false); }
SynchronizedGraph(Graph g) { super(g); elementLock = new ReentrantLock(); synchronizedNodes = new HashMap<String, Node>(); synchronizedEdges = new HashMap<String, Edge>(); for (Node n : g.getEachNode()) synchronizedNodes.put(n.getId(), new SynchronizedNode(this, n)); for (Edge e : g.getEachEdge()) synchronizedEdges.put(e.getId(), new SynchronizedEdge(this, e)); }
// For adding Node To Graph public void AddNodeToGraph(String IP, boolean IsSwitch) { String temp; if (IsSwitch) { temp = "OpenVSwitch"; } else { temp = "EndHost"; } network_graph.addNode(temp + " [" + IP + "]"); Node node = network_graph.getNode(temp + " [" + IP + "]"); node.addAttribute("ui.class", temp); node.addAttribute("ui.label", node.getId()); }
/** * Retrieve a node position from its attributes ("x", "y", "z", or "xy", or "xyz"). * * @param id The node identifier. * @return A newly allocated point containing the (x,y,z) position of the node, or null if the * node is not part of the graph. */ public static Point3 nodePointPosition(Graph graph, String id) { Node node = graph.getNode(id); if (node != null) return nodePointPosition(node); return null; }
/** * Like {@link #nodePointPosition(Graph,String)}, but instead of returning a newly allocated * array, fill up the array given as parameter. This array must have at least three cells. * * @param id The node identifier. * @param pos A point that will receive the node position. * @throws RuntimeException If the node with the given identifier does not exist. */ public static void nodePosition(Graph graph, String id, Point3 pos) { Node node = graph.getNode(id); if (node != null) nodePosition(node, pos); throw new RuntimeException("node '" + id + "' does not exist"); }
@SuppressWarnings("unchecked") private void pathSetShortestPath_facilitate(Node current, Path path, List<Path> paths) { Node source = graph.getNode(this.source_id); if (current != source) { Node next = null; ArrayList<? extends Edge> predecessors = (ArrayList<? extends Edge>) current.getAttribute(identifier + ".predecessors"); while (current != source && predecessors.size() == 1) { Edge e = predecessors.get(0); next = e.getOpposite(current); path.add(current, e); current = next; predecessors = (ArrayList<? extends Edge>) current.getAttribute(identifier + ".predecessors"); } if (current != source) { for (Edge e : predecessors) { Path p = path.getACopy(); p.add(current, e); pathSetShortestPath_facilitate(e.getOpposite(current), p, paths); } } } if (current == source) { paths.add(path); } }
/** * Compute the edge length of the given edge according to its two nodes positions. * * @param id The identifier of the edge. * @return The edge length or -1 if the nodes of the edge have no positions. * @throws RuntimeException If the edge cannot be found. */ public static double edgeLength(Graph graph, String id) { Edge edge = graph.getEdge(id); if (edge != null) return edgeLength(edge); throw new RuntimeException("edge '" + id + "' cannot be found"); }
private void iterateGraph(SimpleNode node, Graph graph) { if (node.isLeaf()) { graph.getNode(node.getId()).addAttribute("ui.class", "leaf"); } else { Iterator<Entry<String, SimpleNode>> childrenIt = node.getChildren().entrySet().iterator(); while (childrenIt.hasNext()) { Entry<String, SimpleNode> next = childrenIt.next(); graph.addNode(next.getValue().getId()).addAttribute("label", next.getValue().getName()); graph .addEdge( node.getId() + next.getValue().getId(), node.getId(), next.getValue().getId(), true) .addAttribute("label", next.getKey()); iterateGraph(next.getValue(), graph); } } }
public BenchPerformance(String fileName, Graph graph) { r = Runtime.getRuntime(); forceGC(); long used1 = r.totalMemory() - r.freeMemory(); g = graph; try { g.read(fileName); } catch (Exception e) { e.printStackTrace(); System.exit(0); } System.out.println( "Graph read: " + g.getNodeCount() + " nodes and " + g.getEdgeCount() + " edges"); for (Node n : g) n.clearAttributes(); for (Edge e : g.getEachEdge()) e.clearAttributes(); forceGC(); long used2 = r.totalMemory() - r.freeMemory(); measureValues = new EnumMap<Measures, Long>(Measures.class); measureValues.put(Measures.MEMORY, used2 - used1); nodeIds = new ArrayList<String>(g.getNodeCount()); for (Node n : g) nodeIds.add(n.getId()); // sort them to be sure that we always work with the same nodes Collections.sort(nodeIds); edgeIds = new ArrayList<String>(g.getEdgeCount()); for (Edge e : g.getEachEdge()) edgeIds.add(e.getId()); Collections.sort(edgeIds); }
// For removing Node From Graph public void RemoveNodeAndEdgesFromGraph(String IP, boolean IsSwitch) { String temp = "EndHost"; if (IsSwitch) { temp = "OpenVSwitch"; } network_graph.removeNode(temp + " [" + IP + "]"); }
private static void createGraph(Network network) throws IOException { graph = new SingleGraph("Tutorial 1"); graph.display(); for (int i = 0; i < network.getNNodes(); i++) { graph.addNode(i + ""); } int[][] edge = network.edges; int[] edges = edge[0]; for (int k = 0; k < edges.length; k++) { int n1 = edge[0][k]; int n2 = edge[1][k]; if (graph.getEdge(n1 + "+" + n2) == null && graph.getEdge(n2 + "+" + n1) == null) { graph.addEdge(n1 + "+" + n2, n1 + "", n2 + ""); } } }
private NetworkInformation() { System.setProperty( "org.graphstream.ui.renderer", "org.graphstream.ui.j2dviewer.J2DGraphRenderer"); network_graph = new SingleGraph("OpenFlow Network"); network_graph.addAttribute("ui.quality"); URL myUrl = null; try { myUrl = new File("Stylesheet.css").toURI().toURL(); } catch (MalformedURLException e) { e.printStackTrace(); } network_graph.addAttribute("ui.stylesheet", "url('" + myUrl.toString() + "')"); network_graph.setStrict(false); network_graph.setAutoCreate(true); switches = new HashMap<String, Switch>(); links = new HashMap<String, Link>(); hosts = new HashMap<String, Host>(); SearchIP = NetworkInformation.Gateway; SearchIP = SearchIP.substring(0, SearchIP.indexOf(".0")); };
public int testFindEdge() { int foo = 0; // for each pair of nodes (n1, n2) find the edge between n1 and n2 long start = System.currentTimeMillis(); for (String id1 : nodeIds) { Node n1 = g.getNode(id1); for (String id2 : nodeIds) { Edge e = n1.getEdgeBetween(id2); if (e != null && e.hasAttribute("foo")) foo++; } } end = System.currentTimeMillis(); measureValues.put(Measures.EDGE_BETWEEN, end - start); // for each pair of nodes (n1, n2) find the edge from n1 to n2 start = System.currentTimeMillis(); for (String id1 : nodeIds) { Node n1 = g.getNode(id1); for (String id2 : nodeIds) { Edge e = n1.getEdgeToward(id2); if (e != null && e.hasAttribute("foo")) foo++; } } end = System.currentTimeMillis(); measureValues.put(Measures.EDGE_TOWARD, end - start); // for each pair of nodes (n1, n2) find the edge from n2 to n1 start = System.currentTimeMillis(); for (String id1 : nodeIds) { Node n1 = g.getNode(id1); for (String id2 : nodeIds) { Edge e = n1.getEdgeFrom(id2); if (e != null && e.hasAttribute("foo")) foo++; } } end = System.currentTimeMillis(); measureValues.put(Measures.EDGE_FROM, end - start); return foo; }
/** * Merge several graphs in one. A new graph is created, that will contain the result. The method * will try to create a graph of the same class that the first graph to merge (it needs to have a * constructor with a String). Else, a MultiGraph is used. * * @param graphs graphs to merge * @return merge result */ public static Graph merge(Graph... graphs) { if (graphs == null) return new DefaultGraph("void-merge"); String id = "merge"; for (Graph g : graphs) id += "-" + g.getId(); Graph result; try { Class<? extends Graph> cls = graphs[0].getClass(); result = cls.getConstructor(String.class).newInstance(id); } catch (Exception e) { logger.warning(String.format("Cannot create a graph of %s.", graphs[0].getClass().getName())); result = new MultiGraph(id); } mergeIn(result, graphs); return result; }
public int testAccessById() { int foo = 0; // access each node by id start = System.currentTimeMillis(); for (String id : nodeIds) { Node n = g.getNode(id); if (n.hasAttribute("foo")) foo++; } end = System.currentTimeMillis(); measureValues.put(Measures.NODE_BY_ID, end - start); // access each edge by id start = System.currentTimeMillis(); for (String id : edgeIds) { Edge e = g.getEdge(id); if (e.hasAttribute("foo")) foo++; } end = System.currentTimeMillis(); measureValues.put(Measures.EDGE_BY_ID, end - start); return foo; }
/* * (non-Javadoc) * * @see org.graphstream.algorithm.Algorithm#compute() */ public void compute() { float min = Float.MAX_VALUE; HashSet<Node> centroid = new HashSet<Node>(); for (Node node : graph.getEachNode()) { float m = 0; APSP.APSPInfo info = node.getAttribute(apspInfoAttribute); if (info == null) System.err.printf("APSPInfo missing. Did you compute APSP before ?\n"); for (Node other : graph.getEachNode()) { if (node != other) { double d = info.getLengthTo(other.getId()); if (d < 0) System.err.printf( "Found a negative length value in centroid algorithm. " + "Is graph connected ?\n"); else m += d; } } if (m < min) { centroid.clear(); centroid.add(node); min = m; } else if (m == min) { centroid.add(node); } } for (Node node : graph.getEachNode()) node.setAttribute( centroidAttribute, centroid.contains(node) ? isInCentroid : isNotInCentroid); centroid.clear(); }
public static void main(String[] args) throws PyException, IOException { String[] argss = new String[] {"C:\\Python27\\python.exe", "D:\\pydemo.py", "D:\\large.txt"}; readInputFile(argss[2], 1); createGraph(network); Process process = null; try { process = Runtime.getRuntime().exec(argss); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } InputStream inputStream = process.getInputStream(); InputStreamReader inputStreamReader = new InputStreamReader(inputStream); BufferedReader bufferedReader = new BufferedReader(inputStreamReader); String line; int i = -1; try { while ((line = bufferedReader.readLine()) != null) { System.out.println(line); if (line.equals("Community: ")) { i++; } else { Node node = graph.getNode(line); if (node != null) { node.addAttribute("ui.label", i + ""); } } } } catch (IOException e) { e.printStackTrace(); } System.out.println("Num of Nodes:" + network.nNodes); System.out.println("Num of Edges:" + network.nEdges); System.out.println("Num of Communities:" + (i + 1)); }
/* * (non-Javadoc) * * @see org.graphstream.algorithm.Algorithm#compute() */ @SuppressWarnings("unchecked") public void compute() { Node source = graph.getNode(this.source_id); // Step 1: Initialize graph for (Node n : graph) { if (n == source) n.addAttribute(identifier + ".distance", 0.0); else n.addAttribute(identifier + ".distance", Double.POSITIVE_INFINITY); // n.addAttribute(identifier+".predecessors",(Object)null); } // Step 2: relax edges repeatedly for (int i = 0; i < graph.getNodeCount(); i++) { for (Edge e : graph.getEachEdge()) { Node n0 = e.getNode0(); Node n1 = e.getNode1(); Double d0 = (Double) n0.getAttribute(identifier + ".distance"); Double d1 = (Double) n1.getAttribute(identifier + ".distance"); Double we = (Double) e.getAttribute(weightAttribute); if (we == null) throw new NumberFormatException( "org.graphstream.algorithm.BellmanFord: Problem with attribute \"" + weightAttribute + "\" on edge " + e); if (d0 != null) { if (d1 == null || d1 >= d0 + we) { n1.addAttribute(identifier + ".distance", d0 + we); ArrayList<Edge> predecessors = (ArrayList<Edge>) n1.getAttribute(identifier + ".predecessors"); if (d1 != null && d1 == d0 + we) { if (predecessors == null) { predecessors = new ArrayList<Edge>(); } } else { predecessors = new ArrayList<Edge>(); } if (!predecessors.contains(e)) { predecessors.add(e); } n1.addAttribute(identifier + ".predecessors", predecessors); } } } } // Step 3: check for negative-weight cycles for (Edge e : graph.getEachEdge()) { Node n0 = e.getNode0(); Node n1 = e.getNode1(); Double d0 = (Double) n0.getAttribute(identifier + ".distance"); Double d1 = (Double) n1.getAttribute(identifier + ".distance"); Double we = (Double) e.getAttribute(weightAttribute); if (we == null) { throw new NumberFormatException( String.format( "%s: Problem with attribute \"%s\" on edge \"%s\"", BellmanFord.class.getName(), weightAttribute, e.getId())); } if (d1 > d0 + we) { throw new NumberFormatException( String.format( "%s: Problem: negative weight, cycle detected on edge \"%s\"", BellmanFord.class.getName(), e.getId())); } } }
/** * Set the id of the node used as source. * * @param nodeId id of the source node */ public void setSource(String nodeId) { if ((source_id == null || !source_id.equals(nodeId)) && graph != null) { source = graph.getNode(nodeId); } this.source_id = nodeId; }
/* * (non-Javadoc) * * @see * org.graphstream.algorithm.Algorithm#init(org.graphstream.graph.Graph) */ public void init(Graph graph) { this.graph = graph; if (getSource() != null) { source = graph.getNode(getSource()); } }
/** * Get the style of a given graph. * * @param graph The node to search for. * @return The graph style. */ public StyleGroup getStyleFor(Graph graph) { String gid = byGraphIdGroups.get(graph.getId()); return groups.get(gid); }
@Override protected Map<IInputOutput<?>, Object> analyzeGraph( IComputationProgress progress, Graph gsGraph, IGenlabGraph genlabGraph, ListOfMessages messages) { // parameters final String graphAttributeNumberComponents = "number of components"; final String vertexAttributeBelongGiantComponent = "belongs_giant_component"; final String vertexAttributeComponentId = "component_id"; // final results final Map<IInputOutput<?>, Object> results = new HashMap<IInputOutput<?>, Object>(); // output graph is... ? IGenlabGraph outputGraph = null; if (!isUsed(GraphStreamConnectedComponents.OUTPUT_GRAPH)) { // we will not create an output graph } else { // someone is using this graph ! if (vertexAttributeBelongGiantComponent == null && vertexAttributeComponentId == null && graphAttributeNumberComponents == null) { // nobody asks for a graph attribute; let's return the same graph as the one provided as // input ! outputGraph = genlabGraph; } else { // someone is interested in some graph attributes; // we have to clone this graph outputGraph = genlabGraph.clone("cloned"); // TODO id ? } } if (outputGraph != null) results.put(GraphStreamConnectedComponents.OUTPUT_GRAPH, outputGraph); // create and run the graphstream algorithm ConnectedComponents cc = new ConnectedComponents(); cc.init(gsGraph); if (vertexAttributeComponentId != null) { // the algo will add the info into the gsGraph cc.setCountAttribute(vertexAttributeComponentId); } cc.compute(); // process its results // ... count of connected components int count = cc.getConnectedComponentsCount(); // (as an output) results.put(GraphStreamConnectedComponents.OUTPUT_COUNT, new Integer(count)); results.put(GraphStreamConnectedComponents.OUTPUT_CONNECTED, new Boolean(count == 1)); // (and as a graph attribute) if (graphAttributeNumberComponents != null && outputGraph != null) { outputGraph.declareGraphAttribute(graphAttributeNumberComponents, Integer.class); } // ... giant component final List<Node> nodesInGiantComponent = cc.getGiantComponent(); results.put( GraphStreamConnectedComponents.OUTPUT_GIANT_COMPONENT_SIZE, nodesInGiantComponent.size()); // TODO add as a graph attribute ? // (if asked, add an attribute for nodes and define its value) if (vertexAttributeBelongGiantComponent != null && outputGraph != null) { outputGraph.declareVertexAttribute(vertexAttributeBelongGiantComponent, Boolean.class); Set<Node> nodesInGiantComponentSet = new HashSet<Node>(nodesInGiantComponent); for (Node n : gsGraph.getNodeSet()) { outputGraph.setVertexAttribute( n.getId(), vertexAttributeBelongGiantComponent, nodesInGiantComponentSet.contains(n)); } } // ... id of each component if (vertexAttributeComponentId != null && outputGraph != null) { outputGraph.declareVertexAttribute(vertexAttributeComponentId, Integer.class); for (Node n : gsGraph.getNodeSet()) { outputGraph.setVertexAttribute( n.getId(), vertexAttributeComponentId, n.getAttribute(vertexAttributeComponentId)); } } // TODO distribution of size ??? // clean graphstream algo internal data cc.terminate(); return results; }
public void execute() { // Toolkit.c final Graph graph = new SingleGraph("roberto"); graph.setStrict(false); graph.addAttribute("ui.stylesheet", "node.important {fill-color: red;}"); graph.addAttribute("ui.quality"); graph.addAttribute("ui.antialias"); BaseGenerator gen = null; // Between 1 and 3 new links per node added. // gen = new BarabasiAlbertGenerator(1);//talvez // gen = new DorogovtsevMendesGenerator();//talvez // gen = new PointsOfInterestGenerator();//gera desconexo // gen = new PreferentialAttachmentGenerator();//parece com lobster // gen = new RandomEuclideanGenerator(2);//+- // gen = new RandomFixedDegreeDynamicGraphGenerator(200, 9.0, // 0.5);//acho que não // gen = new WattsStrogatzGenerator(200, 4, 0.1);//+- // gen = new ClusterGeneratorOld(200); int n = 100; // gen = new LobsterGenerator(5, 5);// sim // gen = new CustomLobsterGenerator(500, 3, 5);// sim // gen = new CustomFlowerSnarkGenerator(100);//sim // gen = new ClusterGenerator(n, 3, 3); //sim // gen = new CustomGridGenerator(110, true, 0.9F, 15, 5);//usado para // gen = new WattsStrogatzGenerator(20, 10, 0.1);//pode ser mas tem que // rodar 2 vezes // gen = new BarabasiAlbertGenerator(1);//talvez - parecido com lobster // gen = new DorogovtsevMendesGenerator();//talvez gen.setRandomSeed(12345); gen.addSink(graph); gen.begin(); while (gen.nextEvents()) ; gen.end(); System.out.println("" + graph.getNodeCount() + " " + graph.getEdgeCount()); // gen.configureNodes(graph); // System.out.println("Amount of important: " + gen.countImportant); Viewer viewer = graph.display(true); // Layout layoutAlgorithm = new SpringBox(); // viewer.enableAutoLayout(layoutAlgorithm); viewer.setCloseFramePolicy(Viewer.CloseFramePolicy.HIDE_ONLY); ViewerListener vl = new MyViewListener(graph, n, 2, gen); ViewerPipe fromViewer = viewer.newViewerPipe(); fromViewer.addViewerListener(vl); fromViewer.addSink(graph); while (loop) { fromViewer.pump(); // or fromViewer.blockingPump(); try { Thread.sleep(100); } catch (InterruptedException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } // try { // Thread.sleep(10000); // } catch (InterruptedException e1) { // // TODO Auto-generated catch block // e1.printStackTrace(); // } }
/** * Clone a given graph with same node/edge structure and same attributes. * * @param g the graph to clone * @return a copy of g */ public static Graph clone(Graph g) { Graph copy; try { Class<? extends Graph> cls = g.getClass(); copy = cls.getConstructor(String.class).newInstance(g.getId()); } catch (Exception e) { logger.warning(String.format("Cannot create a graph of %s.", g.getClass().getName())); copy = new AdjacencyListGraph(g.getId()); } copyAttributes(g, copy); for (int i = 0; i < g.getNodeCount(); i++) { Node source = g.getNode(i); Node target = copy.addNode(source.getId()); copyAttributes(source, target); } for (int i = 0; i < g.getEdgeCount(); i++) { Edge source = g.getEdge(i); Edge target = copy.addEdge( source.getId(), source.getSourceNode().getId(), source.getTargetNode().getId(), source.isDirected()); copyAttributes(source, target); } return copy; }