terminierung bei der evaluation ist noch problematisch

This commit is contained in:
Armin Wolf 2017-08-02 22:42:01 +02:00
parent 2f51b22d38
commit 7f015eaa0c
13 changed files with 269 additions and 124 deletions

View File

@ -1,4 +1,4 @@
import Model.Arrangement;
import Model.LineModel;
import Presenter.Presenter;
import View.MainFrame;
import java.awt.Font;
@ -52,7 +52,7 @@ public class App {
setLookAndFeel(view);
setUIFont (new javax.swing.plaf.FontUIResource(new Font("Verdana",Font.PLAIN, 12)));
view.setPresenter(new Presenter(new Arrangement(), view));
view.setPresenter(new Presenter(new LineModel(), view));
});
}

View File

@ -10,7 +10,7 @@ import java.util.LinkedList;
* @Email: a_wolf28@uni-muenster.de
* @Date: 28.05.2017.
*/
public class Arrangement {
public class LineModel {
private LinkedList<Point> nodes;
private LinkedList<Line> lines;
@ -19,7 +19,7 @@ public class Arrangement {
private Double yMinimum;
private Double yMaximum;
public Arrangement() {
public LineModel() {
nodes = new LinkedList<>();
lines = new LinkedList<>();
}

View File

@ -226,7 +226,7 @@ public class IntersectionCounter {
/**
* Diese Methode liefert nur nach dem Ausführen der <code>run</code> Funktion Sinnvolle Werte.
*/
public void calculateIntersectionAbscissas(Arrangement model){
public void calculateIntersectionAbscissas(LineModel model){
ArrayList<Pair> result = new ArrayList<>();
for (int i = 0; i < inversions.size(); i++) {

View File

@ -1,7 +1,7 @@
package Presenter.Algorithms;
import Model.Line;
import Presenter.Presenter;
import Model.Point;
import java.util.ArrayList;
import java.util.concurrent.ThreadLocalRandom;
@ -13,7 +13,7 @@ import java.util.concurrent.ThreadLocalRandom;
* @Email: a_wolf28@uni-muenster.de
* @Date: 26.06.2017.
*/
public class RandomLineSampler {
public class RandomSampler {
/**
* Diese Methode liefert eine <code>r</code> Elementige zufällige Stichprobe an Geraden.
@ -31,4 +31,22 @@ public class RandomLineSampler {
return sampledLines;
}
/**
* Diese Methode liefert eine <code>r</code> Elementige zufällige Stichprobe van Schnittpunkten.
* @param set Die gesammtmenge der Geraden aus denen gewählt werden soll
* @param r Anzahl der zu wählenden Geraden
* @return <code>r</code> Elementige zufällige Stichprobe an Schnittpunkten
*/
public static ArrayList<Double> run(ArrayList<Point> set, Double r) {
ArrayList<Double> sampledLines = new ArrayList<>();
Integer indexOfEnd = set.size();
for (int i = 0; i < r; i++) {
sampledLines.add(set.get(ThreadLocalRandom.current().nextInt(0, indexOfEnd)).getX());
}
return sampledLines;
}
}

View File

@ -83,7 +83,7 @@ public class RepeatedMedianEstimator extends Observable implements Algorithm {
while (linesInCenterSlab.size() != 1) {
n = linesInCenterSlab.size();
r = Math.ceil(Math.pow(n, beta));
ArrayList<Line> lines = RandomLineSampler.run(linesInCenterSlab, r, linesInCenterSlab.size());
ArrayList<Line> lines = RandomSampler.run(linesInCenterSlab, r, linesInCenterSlab.size());
//For each Sampled Line, compute its median intersection abscissa

View File

@ -61,7 +61,7 @@ public class TheilSenEstimator extends Observable implements Algorithm {
this.yCoordinates = new ArrayList<>();
this.xCoordinates = new ArrayList<>();
this.N = BinomialCoeffizient.run(n, 2);
this.k = Integer.valueOf((int) (N * 0.5));
this.k = Integer.valueOf((int) (N * 0.5))-1;
//Koordinaten werden gespeichert damit am ende
//der y Achsenabschnitt berechnet werden kann
@ -86,18 +86,18 @@ public class TheilSenEstimator extends Observable implements Algorithm {
//Collections.sort(intervalIntersections);
interval = new Interval(NEGATIV_INF, POSITIV_INF);
r = (double) n;
while (true) {
if (this.N <= n) {
break;
} else {
r = Double.valueOf(n);
//Anzahl der Schnittpunkte im Intervall [-Inf, a)
int numberOfIntersections = getIntervalSize(NEGATIV_INF, interval.getLower(), setOfIntersections);
//Randomized Interpolating Search
j = (r / N) * (double) (k - numberOfIntersections);
jA = (int) Math.max(1, Math.floor(j - (1.5 * Math.sqrt(r))));
jB = (int) Math.min(r, Math.floor(j + (1.5 * Math.sqrt(r))));
jA = (int) Math.max(1, Math.floor(j - (3.0 * Math.sqrt(r))));
jB = (int) Math.min(r, Math.floor(j + (3.0 * Math.sqrt(r))));
/* Suche nach einem passenderen und kleineren Intervall
@ -105,11 +105,7 @@ public class TheilSenEstimator extends Observable implements Algorithm {
das Intrvall weniger als 11*N / sqrt(r) Elemente besitzt */
do {
//zufällige Stichprobe
sampledIntersections = randomSampleOfIntersections(intervalIntersections, r);
//TODO: hier vlt. Randomized Select?!
/*Collections.sort(sampledIntersections);
aVariant = sampledIntersections.get(jA);
bVariant = sampledIntersections.get(jB);*/
sampledIntersections = RandomSampler.run(intervalIntersections, r);
aVariant = FastElementSelector.randomizedSelect(sampledIntersections, jA);
bVariant = FastElementSelector.randomizedSelect(sampledIntersections, jB);
} while (!checkCondition());
@ -132,37 +128,13 @@ public class TheilSenEstimator extends Observable implements Algorithm {
*/
private Boolean checkCondition() {
Double kthElement = FastElementSelector.randomizedSelect(xCoordinates, k);
Boolean cond1 = (kthElement > aVariant) && (kthElement <= bVariant);
Boolean cond2 = (getIntervalSize(aVariant+1, bVariant+1, intervalIntersections) <= ((11 * N) / Math.sqrt(r)));
Boolean cond1 = (kthElement >= aVariant) && (
kthElement < bVariant);
Boolean cond2 = (getIntervalSize(aVariant, bVariant, intervalIntersections) <= ((11 * N) / Math.sqrt(r)));
return cond1 && cond2;
}
/**
* Diese Funktion gibt eine <code>r</code> Elementige Stichprobe aus der überegebenene Menge an
* Schnittpunkten. Diese Stichprobe soll zufällig sein. Es können aus gleiche Werte in der Rückgabe
* vertreten sein.
*
* @param set Menge an Schnittpunkten
* @param r Stichprobengröße
* @return Stichprobe
*/
public ArrayList<Double> randomSampleOfIntersections(ArrayList<Point> set, Double r) {
ArrayList<Double> sampledLines = new ArrayList<>();
Random random = new Random(System.currentTimeMillis());
while (sampledLines.size() < r) {
Double x = set.get(random.nextInt(set.size())).getX();
sampledLines.add(x);
}
return sampledLines;
}
/**
* Berechne wieviele von den Schnittpunkten in dem Interval zwischen <code>a</code> und <code>b</code>
* enthalten sind.
@ -219,7 +191,6 @@ public class TheilSenEstimator extends Observable implements Algorithm {
}
return list;
}
@Override

View File

@ -1,6 +1,6 @@
package Presenter.Evaluation;
import Model.Arrangement;
import Model.LineModel;
import Model.Interval;
import Model.Line;
import Presenter.Algorithms.*;
@ -9,6 +9,7 @@ import Presenter.Generator.DatasetGenerator;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Observable;
/**
* Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden.
@ -17,89 +18,82 @@ import java.util.List;
* @Email: a_wolf28@uni-muenster.de
* @Date: 01.08.2017.
*/
public class EvaluateAlgorithms {
public class EvaluateAlgorithms extends Observable{
private Arrangement arrangement;
private Double[] lmsResult;
private Double[] rmResult;
private Double[] tsResult;
private LineModel arrangement;
private Object[] lmsResult;
private Object[] rmResult;
private Object[] tsResult;
private String[] names = {"MSE:\n", "RMSE:\n", "MAE:\n", "MdAE:\n"};
private Thread lmsThread;
private Thread rmThread;
private Thread tsThread;
public EvaluateAlgorithms(){
this.arrangement = new Arrangement();
}
public static void main(String args[]){
EvaluateAlgorithms e = new EvaluateAlgorithms();
try {
e.run();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
public EvaluateAlgorithms(){}
public void run() throws InterruptedException {
Thread thread = new Thread(() -> {
DatasetGenerator generator = new DatasetGenerator();
arrangement.setLines(generator.generateDataset());
this.arrangement = new LineModel();
IntersectionCounter counter = new IntersectionCounter();
counter.run(arrangement.getLines(), new Interval(-99999,99999));
counter.calculateIntersectionAbscissas(arrangement);
});
thread.start();
thread.join();
DatasetGenerator generator = new DatasetGenerator();
arrangement.setLines(generator.generateDataset());
IntersectionCounter counter = new IntersectionCounter();
counter.run(arrangement.getLines(), new Interval(-99999,99999));
counter.calculateIntersectionAbscissas(arrangement);
Thread lms = new Thread(() -> {
lmsThread = new Thread(() -> {
LeastMedianOfSquaresEstimator lmsAlg = new LeastMedianOfSquaresEstimator(arrangement.getLines()
,arrangement.getNodes());
lmsAlg.run();
lmsAlg.getResult();
List<Double> errors = sampsonError(arrangement.getLines(), lmsAlg.getSlope(), lmsAlg.getyInterception());
lmsResult = getResults(errors);
lmsResult = getResults(errors, "Least Median of Squares");
setChanged();
notifyObservers(lmsResult);
});
Thread rm = new Thread(() -> {
rmThread = new Thread(() -> {
RepeatedMedianEstimator rmAlg = new RepeatedMedianEstimator(arrangement.getLines());
rmAlg.run();
rmAlg.getResult();
List<Double> errors = sampsonError(arrangement.getLines(), rmAlg.getSlope(), rmAlg.getyInterception());
rmResult = getResults(errors);
rmResult = getResults(errors, "Repeated-Median");
setChanged();
notifyObservers(rmResult);
});
Thread ts = new Thread(() -> {
tsThread = new Thread(() -> {
TheilSenEstimator tsAlg = new TheilSenEstimator(arrangement.getLines(), arrangement.getNodes());
tsAlg.run();
tsAlg.getResult();
List<Double> errors = sampsonError(arrangement.getLines(), tsAlg.getSlope(), tsAlg.getyInterception());
tsResult = getResults(errors);
tsResult = getResults(errors, "Theil-Sen");
setChanged();
notifyObservers(tsResult);
});
lms.start();
rm.start();
ts.start();
lms.join();
rm.join();
ts.join();
lmsThread.start();
rmThread.start();
tsThread.start();
lmsThread.join();
rmThread.join();
tsThread.join();
for (int i=0;i<4;i++){
System.out.print(names[i]);
System.out.println("LMS: "+ lmsResult[i] + "\tTS: " + tsResult[i] + "\tRM: " + rmResult[i] + "\n\n");
}
}
public Double[] getResults(List<Double> errorValues){
public String[] getResults(List<Double> errorValues, String name){
Double[] ret = new Double[4];
ret[0] = mse(errorValues);
ret[1] = rmse(errorValues);
ret[2] = mae(errorValues);
ret[3] = mdae(errorValues);
String[] ret = new String[6];
ret[0] = name;
ret[1] = mse(errorValues).toString();
ret[2] = rmse(errorValues).toString();
ret[3] = mae(errorValues).toString();
ret[4] = mdae(errorValues).toString();
ret[5] = "eval";
return ret;
}
/* Skalierungs Abhängige Approximationsgüten */

View File

@ -1,6 +1,6 @@
package Presenter.Import;
import Model.Arrangement;
import Model.LineModel;
import Model.Line;
import Presenter.Presenter;
import com.opencsv.CSVReader;
@ -24,12 +24,12 @@ public class DataImporter extends Observable{
private File file;
private CSVReader reader;
private Arrangement model;
private LineModel model;
private Presenter presenter;
public DataImporter(File file, Presenter presenter) {
this.model = new Arrangement();
this.model = new LineModel();
this.presenter = presenter;
this.presenter.setModel(this.model);
//System.out.println(this.model.getLines().size()+ " die Anzahl der aktuellen Lines.");

View File

@ -1,12 +1,13 @@
package Presenter;
import Model.Arrangement;
import Model.LineModel;
import Model.Interval;
import Model.Line;
import Presenter.Algorithms.IntersectionCounter;
import Presenter.Algorithms.LeastMedianOfSquaresEstimator;
import Presenter.Algorithms.RepeatedMedianEstimator;
import Presenter.Algorithms.TheilSenEstimator;
import Presenter.Evaluation.EvaluateAlgorithms;
import Presenter.Generator.DatasetGenerator;
import Presenter.Import.DataImporter;
import View.MainFrame;
@ -28,8 +29,9 @@ import java.util.Observer;
*/
public class Presenter implements Observer {
private Arrangement model;
private LineModel model;
private MainFrame view;
private EvaluateAlgorithms eval;
/* Threads */
private Thread tsThread;
@ -37,16 +39,27 @@ public class Presenter implements Observer {
private Thread lmsThread;
private Thread importThread;
private Thread generatorThread;
private Thread evalThread;
public Presenter(Arrangement model, MainFrame view) {
public Presenter(LineModel model, MainFrame view) {
this.model = model;
this.view = view;
eval = new EvaluateAlgorithms();
eval.addObserver(this);
}
@Override
public void update(Observable o, Object arg) {
String[] result = ((String[]) arg);
if (result.length > 3){
SwingUtilities.invokeLater(() -> {
getView().appendEvalResult(result);
});
}
if (result[0] == "lms"){
SwingUtilities.invokeLater(() -> {
getView().visualizeLMS(Double.parseDouble(result[1]), Double.parseDouble(result[2]));
@ -109,7 +122,7 @@ public class Presenter implements Observer {
}
public void visualizeDualLines() {
view.createArrangement();
view.createDualityDialog();
}
/***************************************************************************************************************************
@ -260,16 +273,34 @@ public class Presenter implements Observer {
}
}
public void startEvaluation(){
if (evalThread == null || !evalThread.isAlive()){
evalThread = new Thread(() ->{
try {
eval.run();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
evalThread.start();
}
}
public void stopEvaluation(){
if (!evalThread.isInterrupted())
evalThread.interrupt();
}
/***************************************************************************************************************************
* Getter und Setter Methoden
***************************************************************************************************************************/
public Arrangement getModel() {
public LineModel getModel() {
return model;
}
public void setModel(Arrangement model) {
public void setModel(LineModel model) {
this.model = model;
}

View File

@ -29,7 +29,7 @@ import java.util.LinkedList;
* @Email: a_wolf28@uni-muenster.de
* @Date: 28.05.2017.
*/
public class ArrangementDialog extends JPanel {
public class DualityDialog extends JPanel {
private LinkedList<Line> lines;
private LinkedList<Point> points;
@ -47,7 +47,7 @@ public class ArrangementDialog extends JPanel {
private Boolean ctrlPressed = false;
private Boolean shiftPressed = false;
public ArrangementDialog() {
public DualityDialog() {
super();
this.setPreferredSize(new Dimension(800, 800));
this.setMinimumSize(new Dimension(800, 800));

View File

@ -39,12 +39,14 @@ public class MainFrame extends JFrame {
private JPanel pane;
private JPanel northPanel;
private ArrangementDialog arrangement;
private DualityDialog arrangement;
private JDialog arrangementDialog;
private PlotDialog plotLMS;
private PlotDialog plotRM;
private PlotDialog plotTS;
private JDialog progressDialog;
private JDialog evaluationDialog;
private Container progressContent;
private JProgressBar progressBar;
@ -53,6 +55,7 @@ public class MainFrame extends JFrame {
private JSplitPane splitpane;
private JScrollPane scrollPane;
private JTabbedPane tabbedPane;
private EvaluationPanel evaluationPanel;
public MainFrame() {
initializeComponents();
@ -74,8 +77,8 @@ public class MainFrame extends JFrame {
* visualisierungs methoden
******************************************************************************************************************/
public void createArrangement() {
arrangement = new ArrangementDialog();
public void createDualityDialog() {
arrangement = new DualityDialog();
arrangementDialog = new JDialog();
arrangementDialog.setTitle("Dual Representation - Dialog");
arrangementDialog.setSize(new Dimension(800, 800));
@ -130,6 +133,30 @@ public class MainFrame extends JFrame {
progressDialog.setVisible(true);
}
public void showEvauluationDialog(){
if (evaluationPanel == null){
SwingUtilities.invokeLater(() -> {
evaluationPanel = new EvaluationPanel(this);
evaluationDialog.add(evaluationPanel);
evaluationDialog.setVisible(true);
});
} else {
SwingUtilities.invokeLater(()->{
evaluationPanel.setVisible(true);
});
}
}
public void appendEvalResult(Object[] res){
SwingUtilities.invokeLater(() -> {
Object[] tmp = res;
evaluationPanel.appendData(res);
evaluationPanel.repaint();
evaluationPanel.revalidate();
});
}
/*******************************************************************************************************************
* init GUI
******************************************************************************************************************/
@ -175,10 +202,11 @@ public class MainFrame extends JFrame {
private void setCloseOperations() {
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
progressDialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
evaluationDialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
}
private void setDimensions() {
this.setMinimumSize(new Dimension(1024,768));
this.setMinimumSize(new Dimension(1024,700));
this.setExtendedState(JFrame.MAXIMIZED_BOTH);
lmsPanel.setMinimumSize(new Dimension(400, 500));
rmPanel.setMinimumSize(new Dimension(400, 500));
@ -186,6 +214,7 @@ public class MainFrame extends JFrame {
output.setMinimumSize(new Dimension(400, 500));
progressDialog.setSize(300, 80);
progressDialog.setResizable(false);
evaluationDialog.setSize(800,500);
}
private void setLayouts() {
@ -200,7 +229,7 @@ public class MainFrame extends JFrame {
lmsPanel = new LMSPanel();
rmPanel = new RMPanel();
tsPanel = new TSPanel();
menupanel = new MenuPanel();
menupanel = new MenuPanel(this);
northPanel = new JPanel();
//Dialogs
@ -208,6 +237,7 @@ public class MainFrame extends JFrame {
progressDialog.setLocationRelativeTo(null);
progressContent = progressDialog.getContentPane();
progressBar = new JProgressBar();
evaluationDialog = new JDialog();
//Panes
tabbedPane = new JTabbedPane();

View File

@ -0,0 +1,88 @@
package View.Panels;
import View.MainFrame;
import javax.swing.*;
import javax.swing.border.TitledBorder;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
/**
* Created by armin on 02.08.17.
*/
public class EvaluationPanel extends JPanel{
private final MainFrame view;
private JTable table;
private JButton start;
private JButton stop;
private JPanel comp;
private JTextField iIteration;
private JTextField iSlope;
private JTextField iYinterception;
private JLabel lIteration;
private JLabel lSlope;
private JLabel lYinterception;
private DefaultTableModel model;
private JPanel buttonPanel;
public EvaluationPanel(MainFrame view){
super();
this.view = view;
this.setLayout(new BorderLayout());
this.setBorder(new TitledBorder("Evaluation der Algorithmen"));
addComponents();
}
private void addComponents(){
lIteration = new JLabel("Interationen");
lSlope = new JLabel("Steigung");
lYinterception = new JLabel("y-Achsenabschnitt");
iIteration = new JTextField();
iSlope = new JTextField();
iYinterception = new JTextField();
start = new JButton("Start");
stop = new JButton("Stop");
buttonPanel = new JPanel(new FlowLayout());
buttonPanel.add(start);
buttonPanel.add(stop);
comp = new JPanel();
comp.setLayout(new GridLayout(0,2));
comp.add(lIteration);
comp.add(iIteration);
comp.add(lSlope);
comp.add(iSlope);
comp.add(lYinterception);
comp.add(iYinterception);
start.addActionListener(e -> {
view.getPresenter().startEvaluation();
});
stop.addActionListener(e -> {
view.getPresenter().stopEvaluation();
});
String[] selections = { "Schätzer","MSE", "RMSE", "MAE", "MdAE"};
model = new DefaultTableModel();
model.setColumnIdentifiers(selections);
table = new JTable(model);
JScrollPane scrollPane = new JScrollPane(table);
scrollPane.setWheelScrollingEnabled(true);
this.add(scrollPane, BorderLayout.CENTER);
this.add(comp, BorderLayout.NORTH);
this.add(buttonPanel, BorderLayout.SOUTH);
}
public void appendData(Object[] row){
model.addRow(row);
this.repaint();
this.revalidate();
}
}

View File

@ -1,12 +1,9 @@
package View.Panels;
import java.awt.BorderLayout;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.SwingConstants;
import View.MainFrame;
import javax.swing.*;
import java.awt.*;
/**
* Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden.
@ -17,22 +14,38 @@ import javax.swing.SwingConstants;
*/
public class MenuPanel extends JPanel {
private MainFrame view;
private JMenuBar menuBar;
private JMenu menu;
private JMenuItem item;
public MenuPanel() {
private JMenu fileMenu;
private JMenu toolsMenu;
private JMenuItem item;
private JMenuItem evaluate;
public MenuPanel(MainFrame view) {
this.view = view;
this.setLayout(new BorderLayout());
this.menuBar = new JMenuBar();
this.menu = new JMenu("File");
this.fileMenu = new JMenu("File");
this.toolsMenu = new JMenu("Tools");
this.item = new JMenuItem("Exit");
this.item.addActionListener(e -> {
System.exit(0);
});
menu.add(item);
menuBar.add(menu);
this.evaluate = new JMenuItem("Evaluation");
this.evaluate.addActionListener(e -> {
view.showEvauluationDialog();
});
fileMenu.add(item);
toolsMenu.add(evaluate);
menuBar.add(fileMenu);
menuBar.add(toolsMenu);
this.add(menuBar, BorderLayout.WEST);
this.add(new JSeparator(SwingConstants.HORIZONTAL), BorderLayout.SOUTH);
}