
Vos solutions informatiques sur mesure
SOCIETE DE SERVICES EN INGENIERIE INFORMATIQUE
On "Generate Graph" click, a graph model is randomly generated on the server side and drawn on the client side.
On "Find path" click, server applies the Dijkstra algorithm looking for the shortest path.
if a path is found, server applies red color to all path elements, on the client side the graph is updated and the shortest path is shown.
<p:growl id="growl" />
<h:form id="mainForm">
<div style="height:500px;width:100%; border:solid 1px; padding:2px">
<p:messages id="messages" showDetail="true"/>
<div id="dijGraphContainer" style="height:70%;">
<p:graphvis2 id="dijGraph" title="Graphe Dijkstra" value="#{demoDijBean.graphModel}" style="border: 1px solid #ddd;margin: Opx 0;"
styleClass="ui-datatable ui-widget" widgetVar="graph" >
</p:graphvis2>
</div>
<p:commandButton id="cmdGenerate" value="Generate Graph" action="#{demoDijBean.generateGraph()}" onsuccess="graph.synchronize(true);" update=":growl mainForm:messages"/>
<p:commandButton id="cmdFindPath" value="Find path" action="#{demoDijBean.applyDijkstra()}" onsuccess="graph.synchronize();" update=":growl mainForm:messages" />
</div>
</h:form>
package graphvis.demo.dijkstra;
import graphvis.demo.common.GraphModelGenerator;
import java.util.List;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
import org.primefaces.model.graphvis.GraphvisEdge;
import org.primefaces.model.graphvis.GraphvisModel;
import org.primefaces.model.graphvis.GraphvisNode;
import org.primefaces.model.graphvis.impl.GraphvisModelImpl;
@ManagedBean
@SessionScoped
public class DemoDijBean {
/**
* the graph model
*/
protected GraphvisModel graphModel = new GraphvisModelImpl();
public GraphvisModel getGraphModel() {
return graphModel;
}
public void setGraphModel(GraphvisModel graphModel) {
this.graphModel = graphModel;
}
/**
* Generate randomly a graph
*/
public void generateGraph(){
GraphModelGenerator.fillGraphModel(graphModel, 10, 30, 100);
FacesContext context = FacesContext.getCurrentInstance();
context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Graph generated with: "
+ graphModel.getNodes().size() + " nodes and "
+ graphModel.getEdges().size() + " edeges.", ""));
graphModel.setLayout("ForceDirected");
}
/**
* lookup for a path and apply color on elements
*/
public void applyDijkstra(){
AlgoDijkstra algo = new AlgoDijkstra(graphModel);
algo.execute(graphModel.getNodes().get(0));
List<GraphvisNode> path = algo.getPath(graphModel.getNodes().get(graphModel.getNodes().size() - 1));
FacesContext context = FacesContext.getCurrentInstance();
//no path found
if(path == null){
context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "No Path found between N1 and N" + (graphModel.getNodes().size() - 1), "" ));
return;
}
//apply color on node and edges of the path
GraphvisNode prevNode = null;
String strPath = "";
for(GraphvisNode pathNode : path){
if(prevNode != null){
for(GraphvisEdge edge : prevNode.getOutcomingEdges()){
if(edge.getTargetNode().equals(pathNode)){
edge.setColor("#ff0000");
graphModel.updateEdge(edge);
}
}
strPath += " -> ";
}
pathNode.setColor("#ff0000");
graphModel.updateNode(pathNode);
strPath += pathNode.getId();
prevNode = pathNode;
}
context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Path found between N1 and N" + (graphModel.getNodes().size() - 1), "Path: " + strPath));
}
}
package conf;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.primefaces.model.graphvis.GraphvisEdge;
import org.primefaces.model.graphvis.GraphvisModel;
import org.primefaces.model.graphvis.GraphvisNode;
/**
* Dijkstra implementation adapted from http://www.vogella.com/articles/JavaAlgorithmsDijkstra/article.html
*/
public class AlgoDijkstra {
private final List<GraphvisNode> nodes;
private final List<GraphvisEdge> edges;
private Set<GraphvisNode> settledNodes;
private Set<GraphvisNode> unSettledNodes;
private Map<GraphvisNode, GraphvisNode> predecessors;
private Map<GraphvisNode, Integer> distance;
public AlgoDijkstra(GraphvisModel GraphvisModel) {
// Create a copy of the array so that we can operate on this array
this.nodes = new ArrayList<GraphvisNode>(GraphvisModel.getNodes());
this.edges = new ArrayList<GraphvisEdge>(GraphvisModel.getEdges());
}
public void execute(GraphvisNode source) {
settledNodes = new HashSet<GraphvisNode>();
unSettledNodes = new HashSet<GraphvisNode>();
distance = new HashMap<GraphvisNode, Integer>();
predecessors = new HashMap<GraphvisNode, GraphvisNode>();
distance.put(source, 0);
unSettledNodes.add(source);
while (unSettledNodes.size() > 0) {
GraphvisNode node = getMinimum(unSettledNodes);
settledNodes.add(node);
unSettledNodes.remove(node);
findMinimalDistances(node);
}
}
private void findMinimalDistances(GraphvisNode node) {
List<GraphvisNode> adjacentNodes = getNeighbors(node);
for (GraphvisNode target : adjacentNodes) {
if (getShortestDistance(target) > getShortestDistance(node)
+ getDistance(node, target)) {
distance.put(target, getShortestDistance(node)
+ getDistance(node, target));
predecessors.put(target, node);
unSettledNodes.add(target);
}
}
}
private int getDistance(GraphvisNode node, GraphvisNode target) {
for (GraphvisEdge GraphvisEdge : edges) {
if (GraphvisEdge.getSourceNode().equals(node)
&& GraphvisEdge.getTargetNode().equals(target)) {
//TODO use getData('distance')
return GraphvisEdge.getWidth();
}
}
throw new RuntimeException("Should not happen");
}
private List<GraphvisNode> getNeighbors(GraphvisNode node) {
List<GraphvisNode> neighbors = new ArrayList<GraphvisNode>();
for (GraphvisEdge GraphvisEdge : edges) {
if (GraphvisEdge.getSourceNode().equals(node)
&& !isSettled(GraphvisEdge.getTargetNode())) {
neighbors.add(GraphvisEdge.getTargetNode());
}
}
return neighbors;
}
private GraphvisNode getMinimum(Set<GraphvisNode> vertexes) {
GraphvisNode minimum = null;
for (GraphvisNode GraphvisNode : vertexes) {
if (minimum == null) {
minimum = GraphvisNode;
} else {
if (getShortestDistance(GraphvisNode) < getShortestDistance(minimum)) {
minimum = GraphvisNode;
}
}
}
return minimum;
}
private boolean isSettled(GraphvisNode GraphvisNode) {
return settledNodes.contains(GraphvisNode);
}
private int getShortestDistance(GraphvisNode destination) {
Integer d = distance.get(destination);
if (d == null) {
return Integer.MAX_VALUE;
} else {
return d;
}
}
/*
* This method returns the path from the source to the selected target and
* NULL if no path exists
*/
public LinkedList<GraphvisNode> getPath(GraphvisNode target) {
LinkedList<GraphvisNode> path = new LinkedList<GraphvisNode>();
GraphvisNode step = target;
// Check if a path exists
if (predecessors.get(step) == null) {
return null;
}
path.add(step);
while (predecessors.get(step) != null) {
step = predecessors.get(step);
path.add(step);
}
// Put it into the correct order
Collections.reverse(path);
return path;
}
}

