Skip to content

Commit

Permalink
Version 0.9 - all main features complete
Browse files Browse the repository at this point in the history
  • Loading branch information
Bennet Krause committed Dec 1, 2016
1 parent 089e0aa commit b1e3469
Show file tree
Hide file tree
Showing 10 changed files with 180 additions and 104 deletions.
24 changes: 23 additions & 1 deletion fdp/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>de.bennetkrause.fdp</groupId>
<artifactId>fdp</artifactId>
<version>0.0.1-SNAPSHOT</version>
<version>0.9-SNAPSHOT</version>
<build>
<plugins>
<plugin>
Expand All @@ -14,6 +14,28 @@
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>fdp.App</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id> <!-- this is used for inheritance merges -->
<phase>package</phase> <!-- bind to the packaging phase -->
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
Expand Down
36 changes: 29 additions & 7 deletions fdp/src/main/java/fdp/ForceDirectedPlacement.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
package fdp;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
Expand All @@ -14,41 +12,65 @@

import fdp.graph.Edge;
import fdp.graph.Vertex;
import javafx.scene.chart.XYChart.Data;
import parsii.tokenizer.ParseException;

public class ForceDirectedPlacement {

public static void simulate(Graph<Vertex, Edge> graph, Parameter p) throws ParseException {
Executors.newSingleThreadExecutor().submit(new Simulation(graph, p));
/**
* Simulates the force-directed placement layout algorithm in a new Thread.
*
* @param graph the graph to layout
* @param parameter parameters for the simulation
* @throws ParseException when the Strings in parameter that represent the force functions are malformed or empty
*/
public static void simulate(Graph<Vertex, Edge> graph, Parameter parameter) throws ParseException {
Executors.newSingleThreadExecutor().submit(new Simulation(graph, parameter));
}

public static Map<Double, Integer> optimizeCoolingRate(GraphConfiguration config, double from, double to, double stepSize, int sampleSize) throws ParseException {
/**
* Tries to find optimal cooling rates for the Graph generated by the given GraphGenerator and the given forces.
*
* @param config the GraphGenerator and parameters as GraphConfiguration object
* @param from initial cooling rate, must be greater 0 and less than 1.
* @param to maximum cooling rate, must be greater 0 and less than 1.
* @param stepSize currently tested cooling rate is increased by stepSize every step, must be greater 0.
* @param sampleSize for every cooling rate tested, sampleSize samples are taken and the average iterations used is calculated from them
* @return a list of XYChart.Data objects, containing a mapping between cooling rate and iterations
* @throws ParseException
*/
public static List<Data<Double, Integer>> optimizeCoolingRate(GraphConfiguration config, double from, double to, double stepSize, int sampleSize) throws ParseException {

Parameter p = config.getParameter();
Map<Double, Integer> chartValues = new HashMap<>();
List<Data<Double, Integer>> chartValues = new ArrayList<>();
ExecutorService exec = Executors.newFixedThreadPool(sampleSize);
List<Future<Integer>> currResults = new ArrayList<>();
config.getParameter().setEquilibriumCriterion(true);
p.setFrameDelay(0);

// need sampleSize objects of the same graph, because we will simulate them in parallel
List<Graph<Vertex, Edge>> graphs = new ArrayList<>();
IntStream.range(0, sampleSize).forEach(i -> graphs.add(config.generateGraph()));

// for every cooling rate to test, simulate sampleSize graph layouts in parallel, retrieve the iterations used until equilibrium,
// and calculate the average number of iterations for that cooling rate
for (double currentCoolingRate = from; currentCoolingRate <= to; currentCoolingRate += stepSize) {
int iterationsUsed = 0;
p.setCoolingRate(currentCoolingRate);
for (int i = 0; i < sampleSize; i++) {
currResults.add(exec.submit(new Simulation(graphs.get(i), p)));
}
// collect the results, i.e. wait for all threads to finish
for (Future<Integer> result : currResults) {
try {
iterationsUsed += result.get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
// get average and save the result
iterationsUsed /= sampleSize;
chartValues.put(currentCoolingRate, iterationsUsed);
chartValues.add(new Data<>(currentCoolingRate, iterationsUsed));

currResults.clear();
}
Expand Down
8 changes: 8 additions & 0 deletions fdp/src/main/java/fdp/GraphConfiguration.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
import fdp.graph.Vertex;
import fdp.graph.VertexFactory;

/**
* Container class that represents a kind of Graph and parameters later used in the simulation.
* @author Bennet
*/
public class GraphConfiguration {

private GraphGenerator<Vertex, Edge, ?> generator;
Expand All @@ -19,6 +23,10 @@ public GraphConfiguration(GraphGenerator<Vertex, Edge, ?> generator, Parameter p
this.setParameter(param);
}

/**
* Generates a new Graph using the GraphGenerator.
* @return
*/
public Graph<Vertex, Edge> generateGraph() {
Graph<Vertex, Edge> graph = new SimpleGraph<>(new EdgeFactory());
this.generator.generateGraph(graph, new VertexFactory(), null);
Expand Down
4 changes: 4 additions & 0 deletions fdp/src/main/java/fdp/Parameter.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package fdp;

/**
* Container class for holding parameters for a simulation.
* @author Bennet
*/
public class Parameter {

private int frameWidth;
Expand Down
9 changes: 5 additions & 4 deletions fdp/src/main/java/fdp/Simulation.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public class Simulation implements Callable<Integer> {
private boolean equilibriumReached = false;

/**
*
* Creates a new Simulation.
*
* @param graph
* @param p
Expand All @@ -55,14 +55,15 @@ public Simulation(Graph<Vertex, Edge> graph, Parameter p) throws ParseException
this.coolingRate = p.getCoolingRate();
this.delay = p.getFrameDelay();

// parse the force strings into Expressions that can be evaluated multiple times
attractiveForceExpr = Parser.parse(p.getAttractiveForce(), scope);
repulsiveForceExpr = Parser.parse(p.getRepulsiveForce(), scope);
}

/**
* Starts the simulation.
*
* @return number of iterations used
* @return number of iterations used until criterion is met
*/
private int startSimulation() {

Expand Down Expand Up @@ -176,7 +177,7 @@ private void simulateStep() {
* @param d
* the distance between the two vertices
* @param k
* @return
* @return amount of force
*/
private double forceAttractive(double d, double k) {
varD.setValue(d);
Expand All @@ -191,7 +192,7 @@ private double forceAttractive(double d, double k) {
* @param d
* the distance between the two vertices
* @param k
* @return
* @return amount of force
*/
private double forceRepulsive(double d, double k) {
varD.setValue(d);
Expand Down
62 changes: 0 additions & 62 deletions fdp/src/main/java/view/CoolingChartJFrame.java

This file was deleted.

33 changes: 33 additions & 0 deletions fdp/src/main/java/view/controller/ChartWindowController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package view.controller;

import java.util.List;

import fdp.GraphConfiguration;
import javafx.fxml.FXML;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.XYChart;
import javafx.scene.chart.XYChart.Data;
import javafx.scene.chart.XYChart.Series;

public class ChartWindowController {

@FXML
private LineChart<Double, Integer> chart;

/**
* Called by the {@link FindOptimumController} to display the result of the cooling rate optimization.
* @param seriesList
* @param configs
*/
void showChart(List<List<Data<Double, Integer>>> seriesList, List<GraphConfiguration> configs) {

chart.setCreateSymbols(false);

for (int i = 0; i < seriesList.size(); i++) {
XYChart.Series<Double, Integer> xySeries = new Series<>();
xySeries.getData().addAll(seriesList.get(i));
chart.getData().add(xySeries);
xySeries.setName("Fa = " + configs.get(i).getParameter().getAttractiveForce() + "; Fr = " + configs.get(i).getParameter().getRepulsiveForce());
}
}
}
Loading

0 comments on commit b1e3469

Please sign in to comment.