Let’s get some coding done
Politechnika Poznańska – April 24th 2018
Basic steps to install GraphStream
In that project, we want the Demos/
folder.
File > Import > Maven > Existing Maven Projects
. Browse to the project (Demos/
folder), Eclipse should recognize the project.pom.xml
file :<!-- ... -->
<groupId>org.graphstream</groupId>
<artifactId>gs-core</artifactId>
<version>1.3</version>
<!-- ... -->
<groupId>org.graphstream</groupId>
<artifactId>gs-algo</artifactId>
<version>1.3</version>
<!-- ... -->
<groupId>org.graphstream</groupId>
<artifactId>gs-ui</artifactId>
<version>1.3</version>
mvn compile
Binaries can be found on the GraphStream Download page graphstream-project.org/download/ :
gs-algo-1.3.zip
, gs-core-1.3.zip
, gs-ui-1.3.zip
.gs-algo-1.3.jar
, gs-core-1.3.jar
, gs-ui-1.3.jar
to the gs-talk-master/Demos/lib
folder of the project.gs-talk
), then properties, then Java build path (left panel), then libraries (right panel), then clic the Add Jars
button, and select our 3 jar files in the gs-talk-master/Demos/lib/
folder.src/org/graphstream/demo/tutorial1/Tutorial1.java
Tutorial1.java
, then Run As > Java Application
public class Tutorial1 {
public static void main(String args[]) {
Graph graph = new SingleGraph("Tutorial 1");
graph.display();
graph.addNode("A");
graph.addNode("B");
graph.addEdge("AB", "A", "B");
graph.addNode("C");
graph.addEdge("BC", "B", "C", true); // Directed edge.
graph.addEdge("CA", "C", "A");
}
}
Maven command line: mvn exec:java-Dexec.mainClass="org.graphstream.demo.tutorial1.Tutorial1"
#Change the Display with CSS
We can improve the display with some CSS:
...
graph.display();
graph.addAttribute("ui.quality");
graph.addAttribute("ui.antialias");
graph.setAttribute("ui.stylesheet", "" +
"edge {" +
" size: 2px;" +
" fill-color: gray;" +
"}");
...
#Access Elements
Node n = graph.addNode("A");
Node n = graph.getNode("A");
#Constructive API vs. Events
graph.removeNode("A");
#Attributes Data stored in the graph, on nodes and edges, are called “attributes”. An attribute is a pair (name,value).
Edge ab = graph.getEdge("AB");
Edge bc = graph.getEdge("BC");
Edge ca = graph.getEdge("CA");
ab.setAttribute("ui.label", "AB");
bc.setAttribute("ui.label", "BC");
ca.setAttribute("ui.label", "CA");
for(String id : new String[]{"A", "B", "C"}){
graph.getNode(id).setAttribute("ui.label", id);
}
graph.setAttribute("ui.stylesheet", "url(data/style.css);");
#Define Attributes
setAttribute()
and a variable number of arguments:ab.setAttribute("aNumber", 10);
bc.setAttribute("anObject", new Double(10));
ca.setAttribute("anArrayOfThings", 1, 2, 3);
#Retrieve Attributes
Several ways to retrieve attributes:
int value1 = ((Number) ab.getAttribute("aNumber")).intValue();
double value2 = bc.getAttribute("anObject");
Object[] value3 = ca.getAttribute("anArrayOfThings");
Special methods are here to simplify things:
#Traversing the graph Iterating through all nodes of the graph is easy:
Equally for edges:
#Other iterators Iterators for nodes:
Iterator<? extends Node> nodes = graph.getNodeIterator();
while(nodes.hasNext()) {
System.out.println(nodes.next().getId());
}
Iterators for edges:
Iterator<? extends Edge> edges = graph.getEdgeIterator();
while(edges.hasNext()) {
System.out.println(edges.next().getId());
}
#Index-based access
Indices for nodes:
int n = graph.getNodeCount();
for(int i=0; i<n; i++) {
System.out.println(graph.getNode(i).getId());
}
Indices for edges:
int n = graph.getEdgeCount();
for(int i=0; i<n; i++) {
System.out.println(graph.getEdge(i).getId());
}
⚠ indices remain the same as long as the graph is unchanged. But as soon as an addition or removal occurs, indices are no longer tied to their old node or edge ⚠
#Travers from nodes and edges
You can also travel the graph using nodes:
import static org.graphstream.algorithm.Toolkit.*;
//...
Node node = randomNode(graph);
for(Edge e: node.getEachEdge()) {
System.out.printf("neighbor %s via %s%n",
e.getOpposite(node).getId(),
e.getId() );
}
Toolkit
is set of often used functions and small algorithms (see the API).You can iterate on directed edges:
Or:
And get the node degree, entering or leaving:
System.out.println(“Node degree %d (entering %d, leaving %d)%n”,
node.getDegree(),
node.getInDegree(),
node.getOutDegree());
#Tutorial 2
###A first dynamic graph
#Sinks - A graph can receive events. It is a sink. - A sink is connected to a source using the Source.addSink(Sink)
method. - Events are filtered by type (Elements Events and Attributes Events) : - addElementSink(ElementSink)
. Nodes and edges are Elements. - addAttributeSink(AttributeSink)
. Data attributes are stored on every element. - A Sink
is both an ElementSink
and AttributeSink
.
#ElementSink ElementSink is an interface
public interface ElementSink {
void nodeAdded( ... );
void nodeRemoved( ... );
void edgeAdded( ... );
void edgeRemoved( ... );
void graphCleared( ... );
void stepBegins( ... );
}
#AttributeSink An attribute sink must follow the interface:
public interface AttributeSink {
void graphAttributeAdded( ... );
void graphAttributeChanged( ... );
void graphAttributeRemoved( ... );
void nodeAttributeAdded( ... );
void nodeAttributeChanged( ... );
void nodeAttributeRemoved( ... );
void edgeAttributeAdded( ... );
void edgeAttributeChanged( ... );
void edgeAttributeRemoved( ... );
}
#Source A source is an interface that only defines methods to handle a set of sinks.
public interface Source {
void addSink(Sink sink);
void removeSink(Sink sink);
void addAttributeSink(AttributeSink sink);
void removeAttributeSink(AttributeSink sink);
void addElementSink(ElementSink sink);
void removeElementSink(ElementSink sink);
void clearElementSinks();
void clearAttributeSinks();
void clearSinks();
}
#A first dynamic graph
Since Graph is a sink let’s create a graph from a set of events generated by a source.
an
for “add node”.ae
for “add edge”.ae "AB" "A" > "B"
adds a directed edge between nodes A
and B
.cn
, ce
and cg
change or add one or more attributes on a node, an edge or the graph.dn
and de
allow to remove nodes, edges.Open the example DGS file in data/tutorial2.dgs
.
st <number>
The ability to remove nodes and edges make the format dynamic.
Add this to the data/tutorial2.dgs
file:
st 2
an "D" label="D"
an "E" label="E"
ae "BD" "B" "D" label="BD"
ae "CE" "C" "E" label="CE"
ae "DE" "D" "E" label="DE"
st 3
de "AB"
st 4
dn "A"
And save it.
#Read the whole file
The file can be read entirely :
#Read the file event by event We can read the DGS file event by event using an input source:
Graph graph = new SingleGraph("Tutorial2");
graph.display();
FileSource source = new FileSourceDGS();
source.addSink( graph );
source.begin("data/tutorial2.dgs");
while( source.nextEvents() );
source.end();
#Read the file step by step - We read the file event by event (line by line in the file), however it still does it as fast as it can. - Note the line while(source.nextEvents());
- Also note that we have to call the begin()
and end()
methods before and after reading to cleanly open and close the file. - Let’s slow down the process :
x
and y
attributes:Then one have to tell the viewer not to compute nodes positions: