sync. gui input with algorithm property

This commit is contained in:
Armin Wolf 2020-04-06 13:07:10 +02:00
parent fa6148dea2
commit 91d3fc4c97
12 changed files with 90 additions and 171 deletions

View File

@ -9,6 +9,7 @@ import de.wwwu.awolf.presenter.data.DataHandler;
import de.wwwu.awolf.presenter.evaluation.EvaluatationHandler;
import de.wwwu.awolf.presenter.util.Logging;
import de.wwwu.awolf.view.ViewController;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ExecutorService;
@ -89,8 +90,8 @@ public abstract class AbstractPresenter implements Flow.Subscriber<Message> {
* @param type algorithm type
* @param lines set of lines
*/
public void executeAlgorithmByType(Algorithm.Type type, Set<Line> lines) {
this.algorithmHandler.runAlgorithmByType(type, lines);
public void executeAlgorithmByType(Algorithm.Type type, final Map<String, String> properties, Set<Line> lines) {
this.algorithmHandler.runAlgorithmByType(type, properties, lines);
}
/**
@ -99,9 +100,9 @@ public abstract class AbstractPresenter implements Flow.Subscriber<Message> {
* @param type algorithm type
* @param lines set of lines
*/
public void executeAlgorithmByType(Algorithm.Type type, Set<Line> lines,
public void executeAlgorithmByType(Algorithm.Type type, final Map<String, String> properties, Set<Line> lines,
BooleanProperty guiFlag) {
this.algorithmHandler.runAlgorithmByType(type, lines, guiFlag);
this.algorithmHandler.runAlgorithmByType(type, properties, lines, guiFlag);
}
/**
@ -109,13 +110,13 @@ public abstract class AbstractPresenter implements Flow.Subscriber<Message> {
*
* @param type algorithm type
*/
public Line executeAlgorithmByType(Algorithm.Type type, BooleanProperty guiFlag) {
public Line executeAlgorithmByType(Algorithm.Type type, final Map<String, String> properties, BooleanProperty guiFlag) {
if (getModel().getSize() == 0) {
Logging.logDebug("No lines in the Model. Nothing to calculate.");
throw new IllegalArgumentException();
} else {
Logging.logDebug("AlgorithmHandler will start " + type.getLabel() + ", with " + getModel().getSize());
return this.algorithmHandler.runAlgorithmByType(type, getModel().getLines(), guiFlag);
return this.algorithmHandler.runAlgorithmByType(type, properties, getModel().getLines(), guiFlag);
}
}

View File

@ -29,9 +29,9 @@ public interface Algorithm extends Callable<Line>, Flow.Publisher<Message> {
void setPresenter(AbstractPresenter presenter);
Map<String, Object> getParameter();
Map<String, String> getParameter();
void setParameter(Map<String, Object> parameter);
void setParameter(Map<String, String> parameter);
enum Type {
LMS("Least Median of Squares"),

View File

@ -17,7 +17,7 @@ public class AlgorithmHandler {
private static AlgorithmHandler instance;
private Map<Algorithm.Type, Algorithm> algorithmMapping;
private Map<Algorithm.Type, Map<String, Object>> algorithmParameters;
private Map<Algorithm.Type, Map<String, String>> algorithmParameters;
private AlgorithmHandler() {
@ -40,8 +40,8 @@ public class AlgorithmHandler {
}
@Nullable
public Line runAlgorithmByType(final Algorithm.Type type, final Set<Line> setOfLines,
final BooleanProperty guiFlag) {
public Line runAlgorithmByType(final Algorithm.Type type, @Nullable final Map<String, String> properties, final Set<Line> setOfLines,
@Nullable final BooleanProperty guiFlag) {
if (guiFlag != null) {
guiFlag.setValue(true);
@ -51,6 +51,11 @@ public class AlgorithmHandler {
Algorithm algorithm = algorithmMapping.get(type);
algorithm.setPresenter(Presenter.getInstance());
algorithm.setInput(setOfLines);
//set properties if needed
if (properties != null) {
algorithm.setParameter(properties);
}
Logging.logDebug("run Algorithm: " + algorithm.getClass().getSimpleName());
//get the executor
@ -80,8 +85,8 @@ public class AlgorithmHandler {
}
@Nullable
public Line runAlgorithmByType(final Algorithm.Type type, final Set<Line> setOfLines) {
return runAlgorithmByType(type, setOfLines, null);
public Line runAlgorithmByType(final Algorithm.Type type, @Nullable final Map<String, String> properties, final Set<Line> setOfLines) {
return runAlgorithmByType(type, properties, setOfLines, null);
}
private void lookUp() {
@ -97,7 +102,7 @@ public class AlgorithmHandler {
});
}
public Map<String, Object> getAlgorithmParametersByType(Algorithm.Type type) {
public Map<String, String> getAlgorithmParametersByType(Algorithm.Type type) {
return algorithmParameters.get(type);
}
}

View File

@ -36,7 +36,6 @@ public class LeastMedianOfSquaresEstimator implements Algorithm {
private List<Line> setOfLines;
private int n;
private double quantileError;
private int kPlus;
private int kMinus;
private Queue<Interval> intervals;
@ -45,20 +44,16 @@ public class LeastMedianOfSquaresEstimator implements Algorithm {
private Line sigmaMin;
private double heightsigmaMin;
private double intersectionsPoint;
private double constant;
private double slope;
private double yInterception;
private Flow.Subscriber<? super AlgorithmMessage> subscriber;
private Map<String, Object> parameter;
private Map<String, String> parameter;
public LeastMedianOfSquaresEstimator() {
quantileError = 0.1;
constant = 0.5;
parameter = new HashMap<>();
parameter.put("Quantile Error", quantileError);
parameter.put("Constant", constant);
parameter.put("Quartile Error", String.valueOf(0.1));
parameter.put("Constant", String.valueOf(0.5));
}
/**
@ -70,9 +65,10 @@ public class LeastMedianOfSquaresEstimator implements Algorithm {
@Override
public Line call() {
Logging.logDebug("Parameter\nQuartile Error: " + Double.parseDouble(parameter.get("Quartile Error")) + ", Constant: " + Double.parseDouble(parameter.get("Constant")));
this.n = setOfLines.size();
double qPlus = 0.5;
double qMinus = qPlus * (1 - quantileError);
double qMinus = qPlus * (1 - Double.parseDouble(parameter.get("Quartile Error")));
kMinus = (int) Math.ceil(n * qMinus);
kPlus = (int) Math.ceil(n * qPlus);
@ -105,7 +101,7 @@ public class LeastMedianOfSquaresEstimator implements Algorithm {
int numberOfIntersections = countInversions(interval);
//(b.) apply plane sweep
if ((constant * n) >= numberOfIntersections) {
if ((Double.parseDouble(parameter.get("Constant")) * n) >= numberOfIntersections) {
sigmaMin = pseudoSweep(interval);
} else {
//(c.) otherwise....
@ -168,12 +164,12 @@ public class LeastMedianOfSquaresEstimator implements Algorithm {
}
@Override
public Map<String, Object> getParameter() {
public Map<String, String> getParameter() {
return this.parameter;
}
@Override
public void setParameter(Map<String, Object> parameter) {
public void setParameter(Map<String, String> parameter) {
this.parameter = parameter;
}
@ -425,20 +421,6 @@ public class LeastMedianOfSquaresEstimator implements Algorithm {
this.n = n;
}
/**
* @param quantileError Parameter quantile Fehler
*/
public void setQuantileError(double quantileError) {
this.quantileError = quantileError;
}
/**
* @param kMinus kMinus index
*/
public void setkMinus(int kMinus) {
this.kMinus = kMinus;
}
/**
* @return duale Streifen Sigma_min
*/
@ -446,27 +428,6 @@ public class LeastMedianOfSquaresEstimator implements Algorithm {
return sigmaMin;
}
/**
* @param sigmaMin duale Streifen Sigma_min
*/
public void setSigmaMin(Line sigmaMin) {
this.sigmaMin = sigmaMin;
}
/**
* @param heightsigmaMin höhe von Sigma_min
*/
public void setHeightsigmaMin(double heightsigmaMin) {
this.heightsigmaMin = heightsigmaMin;
}
/**
* @param constant Parameter Konstante
*/
public void setConstant(Double constant) {
this.constant = constant;
}
/**
* @return Steigung
*/

View File

@ -34,8 +34,6 @@ public class RepeatedMedianEstimator implements Algorithm {
private static final Algorithm.Type type = Type.RM;
private AbstractPresenter presenter;
private List<Line> setOfLines;
private Interval interval;
private Interval original;
@ -55,18 +53,15 @@ public class RepeatedMedianEstimator implements Algorithm {
private double k;
private double kLow;
private double kHigh;
private double beta;
private double slope;
private double yInterception;
private Flow.Subscriber<? super AlgorithmMessage> subscriber;
private Map<String, Object> parameter;
private Map<String, String> parameter;
public RepeatedMedianEstimator() {
beta = 0.5;
parameter = new HashMap<>();
parameter.put("Beta", beta);
parameter.put("Beta", String.valueOf(0.5));
}
/**
@ -75,7 +70,6 @@ public class RepeatedMedianEstimator implements Algorithm {
* Paper: Matousek, Jiri, D. M. Mount und N. S. Netanyahu Efficient Randomized Algorithms for the Repeated Median Line Estimator. 1998 Algorithmica 20.2, S. 136150
*/
public Line call() {
n = setOfLines.size();
interval = new Interval(-10000, 10000);
original = new Interval(-10000, 10000);
@ -104,7 +98,7 @@ public class RepeatedMedianEstimator implements Algorithm {
while (countCenterSlab > 1) {
n = countCenterSlab;
r = Math.ceil(Math.pow(n, beta));
r = Math.ceil(Math.pow(n, Double.parseDouble(parameter.get("Beta"))));
List<Line> lines = RandomSampler.run(setOfLines, r);
//Für jede Gerade aus der Stichprobe wird der Schnittpunkt mit der medianen
@ -157,7 +151,6 @@ public class RepeatedMedianEstimator implements Algorithm {
@Override
public void setPresenter(AbstractPresenter presenter) {
this.presenter = presenter;
subscribe(presenter);
}
@ -286,13 +279,6 @@ public class RepeatedMedianEstimator implements Algorithm {
this.n = n;
}
/**
* @param beta Parameter Beta
*/
public void setBeta(Double beta) {
this.beta = beta;
}
/**
* @return Steigung
*/
@ -307,67 +293,18 @@ public class RepeatedMedianEstimator implements Algorithm {
return yInterception;
}
/**
* @return temporäres untere Intervallgrenze
*/
public Double getkLow() {
return kLow;
}
/**
* @param kLow temporäres untere Intervallgrenze
*/
public void setkLow(Double kLow) {
this.kLow = kLow;
}
/**
* @return temporäres oberes Intervallgrenze
*/
public Double getkHigh() {
return kHigh;
}
/**
* @param kHigh temporäres oberes Intervallgrenze
*/
public void setkHigh(Double kHigh) {
this.kHigh = kHigh;
}
/**
* @return verteilung der Punkte
*/
public int getCountLeftSlab() {
return countLeftSlab;
}
/**
* @return verteilung der Punkte
*/
public int getCountCenterSlab() {
return countCenterSlab;
}
/**
* @return verteilung der Punkte
*/
public int getCountRightSlab() {
return countRightSlab;
}
@Override
public void subscribe(Flow.Subscriber<? super Message> subscriber) {
this.subscriber = subscriber;
}
@Override
public Map<String, Object> getParameter() {
public Map<String, String> getParameter() {
return this.parameter;
}
@Override
public void setParameter(Map<String, Object> parameter) {
public void setParameter(Map<String, String> parameter) {
this.parameter = parameter;
}
}

View File

@ -33,16 +33,8 @@ public class TheilSenEstimator implements Algorithm {
private static final Algorithm.Type type = Type.TS;
private final double POSITIV_INF = 9999.0;
private final double NEGATIV_INF = -9999.0;
private final double EPSILON = 0.00001;
private List<Line> setOfLines;
//Hilfsvariablen (siehe original Paper)
private double j;
private int jA;
private int jB;
private double r;
private int n;
private double N;
private int k;
//Intervall und die temporaeren Grenzen
@ -52,8 +44,7 @@ public class TheilSenEstimator implements Algorithm {
private double slope;
private double yInterception;
private Flow.Subscriber<? super AlgorithmMessage> subscriber;
private AbstractPresenter presenter;
private Map<String, Object> parameter;
private Map<String, String> parameter;
/**
@ -62,11 +53,13 @@ public class TheilSenEstimator implements Algorithm {
*/
public Line call() {
this.n = this.setOfLines.size();
int n = this.setOfLines.size();
this.N = BinomialCoeffizient.run(n, 2);
//this.k = Integer.valueOf((int) (N * 0.5)) - 1;
this.k = (int) (N / 2);
double POSITIV_INF = 9999.0;
double NEGATIV_INF = -9999.0;
interval = new Interval(NEGATIV_INF, POSITIV_INF);
//damit eine initiale Ordnung herscht
//Collections.sort(intervalIntersections);
@ -75,6 +68,7 @@ public class TheilSenEstimator implements Algorithm {
List<Point> intervalIntersections = new LinkedList<>(IntersectionComputer.getInstance()
.compute(setOfLines, interval.getLower(), interval.getUpper()));
while (true) {
double EPSILON = 0.00001;
if (this.N <= n
|| (Math.abs(interval.getUpper() - interval.getLower())) < EPSILON) {
break;
@ -84,9 +78,10 @@ public class TheilSenEstimator implements Algorithm {
interval.getLower());
//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))));
//Hilfsvariablen (siehe original Paper)
double j = (r / N) * (double) (k - numberOfIntersections);
int jA = (int) Math.max(1, Math.floor(j - (1.5 * Math.sqrt(r))));
int jB = (int) Math.min(r, Math.floor(j + (1.5 * Math.sqrt(r))));
/* Suche nach einem passenderen und kleineren Intervall
@ -103,7 +98,7 @@ public class TheilSenEstimator implements Algorithm {
bVariant = FastElementSelector
.randomizedSelect(getIntersectionAbscissas(sampledIntersections),
jB);
} while (!checkCondition());
} while (!checkCondition(NEGATIV_INF));
interval.setLower(aVariant);
interval.setUpper(bVariant);
@ -128,7 +123,6 @@ public class TheilSenEstimator implements Algorithm {
@Override
public void setPresenter(AbstractPresenter presenter) {
this.presenter = presenter;
subscribe(presenter);
}
@ -145,12 +139,12 @@ public class TheilSenEstimator implements Algorithm {
*
* @return Boolscher Wert ob die Bedingung erfüllt ist
*/
private Boolean checkCondition() {
private Boolean checkCondition(final double lowerBound) {
//Double kthElement = FastElementSelector.randomizedSelect(xCoordinates, k);
//Boolean cond1 = (kthElement > aVariant) && (kthElement <= bVariant);
int lowerCount = getIntervalSize(NEGATIV_INF, aVariant);
int higherCount = getIntervalSize(NEGATIV_INF, bVariant);
int lowerCount = getIntervalSize(lowerBound, aVariant);
int higherCount = getIntervalSize(lowerBound, bVariant);
Boolean conda = k > lowerCount;
Boolean condb = k <= higherCount;
@ -208,7 +202,8 @@ public class TheilSenEstimator implements Algorithm {
yCoords.add(p.getY());
}
double pseudoIndex = getIntervalSize(NEGATIV_INF, interval.getLower()) * 1.0;
//TODO
double pseudoIndex = getIntervalSize(-9999.0, interval.getLower()) * 1.0;
m = FastElementSelector.randomizedSelect(resultAbscissas, k - pseudoIndex);
Set<Double> unique = new LinkedHashSet<>(yCoords);
@ -249,12 +244,12 @@ public class TheilSenEstimator implements Algorithm {
}
@Override
public Map<String, Object> getParameter() {
public Map<String, String> getParameter() {
return this.parameter;
}
@Override
public void setParameter(Map<String, Object> parameter) {
public void setParameter(Map<String, String> parameter) {
this.parameter = parameter;
}
}

View File

@ -33,7 +33,7 @@ public class NaiveLeastMedianOfSquaresEstimator implements Algorithm {
private double ds, b, m;
private Flow.Subscriber<? super Message> subscriber;
private AbstractPresenter presenter;
private Map<String, Object> parameter;
private Map<String, String> parameter;
public NaiveLeastMedianOfSquaresEstimator() {
parameter = new HashMap<>();
@ -148,12 +148,12 @@ public class NaiveLeastMedianOfSquaresEstimator implements Algorithm {
}
@Override
public Map<String, Object> getParameter() {
public Map<String, String> getParameter() {
return this.parameter;
}
@Override
public void setParameter(Map<String, Object> parameter) {
public void setParameter(Map<String, String> parameter) {
this.parameter = parameter;
}
}

View File

@ -36,7 +36,7 @@ public class NaiveRepeatedMedianEstimator implements Algorithm {
private double medianY;
private Flow.Subscriber<? super Message> subscriber;
private AbstractPresenter presenter;
private Map<String, Object> parameter;
private Map<String, String> parameter;
public NaiveRepeatedMedianEstimator() {
parameter = new HashMap<>();
@ -150,12 +150,12 @@ public class NaiveRepeatedMedianEstimator implements Algorithm {
}
@Override
public Map<String, Object> getParameter() {
public Map<String, String> getParameter() {
return this.parameter;
}
@Override
public void setParameter(Map<String, Object> parameter) {
public void setParameter(Map<String, String> parameter) {
this.parameter = parameter;
}

View File

@ -31,7 +31,7 @@ public class NaiveTheilSenEstimator implements Algorithm {
private double yInterception;
private Flow.Subscriber<? super Message> subscriber;
private AbstractPresenter presenter;
private Map<String, Object> parameter;
private Map<String, String> parameter;
public NaiveTheilSenEstimator() {
parameter = new HashMap<>();
@ -100,12 +100,12 @@ public class NaiveTheilSenEstimator implements Algorithm {
}
@Override
public Map<String, Object> getParameter() {
public Map<String, String> getParameter() {
return this.parameter;
}
@Override
public void setParameter(Map<String, Object> parameter) {
public void setParameter(Map<String, String> parameter) {
this.parameter = parameter;
}

View File

@ -36,7 +36,7 @@ public class AlgorithmComparison {
type = value;
}
Line line = algorithmHandler.runAlgorithmByType(type, lines);
Line line = algorithmHandler.runAlgorithmByType(type, null, lines);
comparisonResult.put(type, line);
}
return comparisonResult;

View File

@ -4,8 +4,10 @@ import de.wwwu.awolf.model.dao.Line;
import de.wwwu.awolf.model.dao.LineModel;
import de.wwwu.awolf.presenter.algorithms.Algorithm;
import de.wwwu.awolf.view.services.ButtonClickService;
import java.util.HashMap;
import java.util.Map;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.fxml.FXML;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
@ -16,6 +18,7 @@ import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.VBox;
import javax.annotation.Nullable;
public class AlgorithmTabController {
@ -29,7 +32,7 @@ public class AlgorithmTabController {
private Button startButton;
private Algorithm.Type algorithmType;
private Map<String, Object> properties;
private Map<String, SimpleObjectProperty<String>> properties;
private LineModel model;
public AlgorithmTabController() {
@ -56,7 +59,8 @@ public class AlgorithmTabController {
borderPane.setPadding(new Insets(10, 0, 10, 0));
//text field for the input
TextField textField = new TextField(String.valueOf(value));
TextField textField = new TextField(String.valueOf(value.get()));
textField.textProperty().bindBidirectional(value);
//label
Label label = new Label(key);
@ -73,8 +77,7 @@ public class AlgorithmTabController {
BooleanProperty booleanProperty = startButton.disableProperty();
startButton.setOnAction(event -> {
ButtonClickService buttonClickService = new ButtonClickService(algorithmType,
booleanProperty);
ButtonClickService buttonClickService = new ButtonClickService(algorithmType, getProperties(), booleanProperty);
buttonClickService.start();
}
);
@ -110,12 +113,26 @@ public class AlgorithmTabController {
this.algorithmType = algorithmType;
}
public Map<String, Object> getProperties() {
return properties;
@Nullable
public Map<String, String> getProperties() {
if (properties == null) {
return null;
} else {
HashMap<String, String> props = new HashMap<>();
properties.forEach((key, value) -> {
props.put(key, value.get());
});
return props;
}
}
public void setProperties(Map<String, Object> properties) {
this.properties = properties;
public void setProperties(Map<String, String> props) {
if (props != null && !props.isEmpty()) {
properties = new HashMap<>();
props.forEach((key, value) -> {
properties.put(key, new SimpleObjectProperty<>(value));
});
}
}
public Button getStartButton() {

View File

@ -3,6 +3,7 @@ package de.wwwu.awolf.view.services;
import de.wwwu.awolf.model.dao.Line;
import de.wwwu.awolf.presenter.Presenter;
import de.wwwu.awolf.presenter.algorithms.Algorithm;
import java.util.Map;
import javafx.beans.property.BooleanProperty;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
@ -10,10 +11,12 @@ import javafx.concurrent.Task;
public class ButtonClickService extends Service<Boolean> {
private final BooleanProperty startButtonDisabled;
private final Map<String, String> properties;
private Algorithm.Type type;
public ButtonClickService(final Algorithm.Type algorithmType, final BooleanProperty startButtonDisabled) {
public ButtonClickService(final Algorithm.Type algorithmType, final Map<String, String> properties, final BooleanProperty startButtonDisabled) {
this.startButtonDisabled = startButtonDisabled;
this.properties = properties;
this.type = algorithmType;
}
@ -25,7 +28,7 @@ public class ButtonClickService extends Service<Boolean> {
protected Boolean call() throws Exception {
try {
Line line = Presenter.getInstance()
.executeAlgorithmByType(type, startButtonDisabled);
.executeAlgorithmByType(type, properties, startButtonDisabled);
if (line != null) {
return true;
}