From 2fdaa0aa3c454aa3ee36e267e80f324170685a56 Mon Sep 17 00:00:00 2001
From: Lukas Ettel <34522828+LukasEttel@users.noreply.github.com>
Date: Mon, 8 Jun 2020 11:37:11 +0200
Subject: [PATCH] release

---
 pom.xml                                       |  6 +-
 .../ba/yoshikoWrapper/core/ParameterSet.java  |  8 +-
 .../cytoUtil/GraphAnalyzer.java               | 89 +++++++++++++++++++
 .../graphModel/YoshikoCluster.java            |  4 +-
 .../swing/components/EditCostPanel.java       | 18 +++-
 .../swing/components/MainPanel.java           | 23 +++--
 .../swing/components/ResultPanel.java         | 13 +--
 .../taskFactories/CommandTaskFactory.java     |  6 +-
 .../yoshikoWrapper/tasks/AlgorithmTask.java   |  4 +-
 .../yoshikoAlgorithm/ClusteringAlgorithm.java |  1 -
 .../yoshikoAlgorithm/GraphTranslator.java     | 67 +++++++++++++-
 .../YoshikoAlgoritmController.java            |  1 +
 12 files changed, 204 insertions(+), 36 deletions(-)

diff --git a/pom.xml b/pom.xml
index 8c1c573..1fbd33d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -32,8 +32,8 @@
 	</properties>
 
 	<groupId>de.hhu.ba</groupId>
-	<artifactId>yoshikoStandalone</artifactId>
-	<version>0.1.1</version>
+	<artifactId>YoshikoStandalone</artifactId>
+	<version>1.0.0</version>
 
 	<name>YoshikoStandalone</name>
 
@@ -130,7 +130,7 @@
 		<dependency>
 			<groupId>junit</groupId>
 			<artifactId>junit</artifactId>
-			<version>4.8.2</version>
+			<version>4.11</version>
 			<scope>test</scope>
 		</dependency>
 		<dependency>
diff --git a/src/main/java/de/hhu/ba/yoshikoWrapper/core/ParameterSet.java b/src/main/java/de/hhu/ba/yoshikoWrapper/core/ParameterSet.java
index 48f1639..f267e05 100644
--- a/src/main/java/de/hhu/ba/yoshikoWrapper/core/ParameterSet.java
+++ b/src/main/java/de/hhu/ba/yoshikoWrapper/core/ParameterSet.java
@@ -54,6 +54,8 @@ public class ParameterSet implements TunableValidator
 	public double defaultInsertionCost = -1;
 	@Tunable(description="The default deletion cost that is to be used for edges without an associated weight",context="nogui")
 	public double defaultDeletionCost = 1;
+	@Tunable(description="The threshold to tackle the problem of a completly poitive graph", context="nogui")
+	public double threshold = 0;
 
 	@Tunable(description="A bitmask representing which reduction rules should be used",context="nogui")
 	public String reductionRulesBitMask = "000000";
@@ -80,7 +82,11 @@ public class ParameterSet implements TunableValidator
 
 	@Tunable(description="Determines the number of clusters that are to be generated. -1 generates the optimal amount of clusters in the sense of WCE",context="nogui")
 	public int clusterCount = -1;
-	
+
+
+	//ugly passing of variables
+	public boolean containsOnlyPositiveEdges;
+	public double recomendetTreshold;
 	/**
 	 * Default constructor, initializes the column mappings to provide a selection of fitting columns
 	 */
diff --git a/src/main/java/de/hhu/ba/yoshikoWrapper/cytoUtil/GraphAnalyzer.java b/src/main/java/de/hhu/ba/yoshikoWrapper/cytoUtil/GraphAnalyzer.java
index 24ca2d5..a6b8a07 100644
--- a/src/main/java/de/hhu/ba/yoshikoWrapper/cytoUtil/GraphAnalyzer.java
+++ b/src/main/java/de/hhu/ba/yoshikoWrapper/cytoUtil/GraphAnalyzer.java
@@ -2,6 +2,8 @@ package de.hhu.ba.yoshikoWrapper.cytoUtil;
 
 import java.util.List;
 
+import de.hhu.ba.yoshikoWrapper.core.NetworkParsingException;
+import de.hhu.ba.yoshikoWrapper.core.ParameterSet;
 import org.cytoscape.model.CyColumn;
 import org.cytoscape.model.CyEdge;
 import org.cytoscape.model.CyNetwork;
@@ -160,4 +162,91 @@ public class GraphAnalyzer {
 		}
 		return false;
 	}
+
+	public static double recommendThreshold(CyNetwork net, ParameterSet parameterSet) throws NetworkParsingException{
+		double threshold = parameterSet.threshold;
+		double maxEdgeWeight = Double.NEGATIVE_INFINITY;
+		double minEdgeWeight = Double.POSITIVE_INFINITY;
+
+		for (CyEdge edge : net.getEdgeList()){
+			double weight;
+			weight = extractValue(edge,net, parameterSet);
+			weight -= threshold;
+
+
+			if (weight < minEdgeWeight){
+				minEdgeWeight = weight;
+			}
+			if (weight > maxEdgeWeight){
+				maxEdgeWeight = weight;
+			}
+		}
+
+		if (minEdgeWeight == maxEdgeWeight){
+			return 0;
+		}
+
+		if (minEdgeWeight >= 0){
+			return (maxEdgeWeight+minEdgeWeight)/2;
+		}
+		return 0;
+	}
+
+	private static double extractValue(CyEdge edge, CyNetwork network,ParameterSet parameterSet) throws NetworkParsingException {
+		CyColumn weightColumn = parameterSet.getWeightColumn();
+
+		//Parse editing costs
+		double weight = parameterSet.defaultDeletionCost;
+
+		//Fetch entry and check if it exists
+		CyRow edgeEntry = network.getRow(edge);
+
+		//Check if the column contains an entry for the respective edge
+		//It is possible, that there are missing entries
+		if (parameterSet.weightColumn != null){
+			if (edgeEntry.get(weightColumn.getName(), weightColumn.getType()) != null){
+				if (weightColumn.getType() == Integer.class) {
+					weight = 1.0*edgeEntry.get(weightColumn.getName(), Integer.class);
+				}
+				else if (weightColumn.getType() == Double.class) {
+					weight = edgeEntry.get(weightColumn.getName(), Double.class);
+				}
+			}
+		}
+
+
+		CyColumn permanentColumn = parameterSet.getPermanentColumn();
+		CyColumn forbiddenColumn = parameterSet.getForbiddenColumn();
+
+		//Parse Forbidden/Permanent markers
+		boolean forbidden = false;
+		boolean permanent = false;
+
+		if (permanentColumn != null) {
+			//Additional check as it is not required to have a value in every row
+			if (edgeEntry.get(permanentColumn.getName(), Boolean.class) != null) {
+				permanent =  (boolean)edgeEntry.get(permanentColumn.getName(), Boolean.class);
+			}
+		}
+		if (forbiddenColumn != null) {
+			//Additional check as it is not required to have a value in every row
+			if (edgeEntry.get(forbiddenColumn.getName(), Boolean.class) != null) {
+				forbidden =  (boolean)edgeEntry.get(forbiddenColumn.getName(), Boolean.class);
+			}
+		}
+
+		//Check for edges that are forbidden AND permanent -> Throw exception
+		if (forbidden && permanent) {
+			throw new NetworkParsingException("dualInfinityError");
+		}
+
+
+		if(permanent){
+			return Double.POSITIVE_INFINITY;
+		}else if (forbidden){
+			return Double.NEGATIVE_INFINITY;
+		}
+
+		return weight;
+	}
 }
\ No newline at end of file
diff --git a/src/main/java/de/hhu/ba/yoshikoWrapper/graphModel/YoshikoCluster.java b/src/main/java/de/hhu/ba/yoshikoWrapper/graphModel/YoshikoCluster.java
index 57c4563..40beaed 100644
--- a/src/main/java/de/hhu/ba/yoshikoWrapper/graphModel/YoshikoCluster.java
+++ b/src/main/java/de/hhu/ba/yoshikoWrapper/graphModel/YoshikoCluster.java
@@ -164,8 +164,8 @@ public class YoshikoCluster {
 			)
 		);
 
-		view.setVisualProperty(NETWORK_WIDTH, new Double(width));
-		view.setVisualProperty(NETWORK_HEIGHT, new Double(height));
+		view.setVisualProperty(NETWORK_WIDTH, (double) width);
+		view.setVisualProperty(NETWORK_HEIGHT, (double) height);
 		view.fitContent();
 
 		StyleManager.style(view, CyCore.visualMappingManager.getCurrentVisualStyle());
diff --git a/src/main/java/de/hhu/ba/yoshikoWrapper/swing/components/EditCostPanel.java b/src/main/java/de/hhu/ba/yoshikoWrapper/swing/components/EditCostPanel.java
index 257ff59..d86de66 100644
--- a/src/main/java/de/hhu/ba/yoshikoWrapper/swing/components/EditCostPanel.java
+++ b/src/main/java/de/hhu/ba/yoshikoWrapper/swing/components/EditCostPanel.java
@@ -42,11 +42,13 @@ public class EditCostPanel extends JPanel {
 
 	private final DoubleInputField  icField;
 	private final DoubleInputField dcField;
+	private final DoubleInputField threshholdField;
 	
 	private final JSeparator separator;
 
 	private final JLabel icLabel;
 	private final JLabel dcLabel;
+	private final JLabel threshholdLable;
 
 	//private final HelpButton helpButton;
 
@@ -59,18 +61,21 @@ public class EditCostPanel extends JPanel {
 
 		icField = new DoubleInputField(Double.NEGATIVE_INFINITY,0);
 		dcField = new DoubleInputField(0,Double.POSITIVE_INFINITY);
+		threshholdField = new DoubleInputField(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY);
 
 		icField.setText("-1.0");
 		icField.setToolTipText(LocalizationManager.get("icTooltip"));
 		dcField.setText("1.0");
+		threshholdField.setText("0.0");
 		
 		separator = new JSeparator(JSeparator.HORIZONTAL);
 
 		icLabel = new JLabel(LocalizationManager.get("defaultInsertion"));
-		dcLabel = new JLabel(LocalizationManager.get("defaultDeletion"));
+		dcLabel = new JLabel("Default deletion cost:");
+		threshholdLable = new JLabel("Threshold for weight:");
 
 		//Add components
-		SwingUtil.addAll(this,columnMapper,separator,icLabel,icField,dcLabel,dcField);
+		SwingUtil.addAll(this,columnMapper,separator,icLabel,icField,dcLabel,dcField, threshholdLable, threshholdField);
 		//SwingUtil.addAll(helpButton);
 
 
@@ -86,11 +91,13 @@ public class EditCostPanel extends JPanel {
 						.addGroup(layout.createParallelGroup(Alignment.LEADING)
 								.addComponent(icLabel)
 								.addComponent(dcLabel)
+								.addComponent(threshholdLable)
 						)
 						.addGap(4)
 						.addGroup(layout.createParallelGroup(Alignment.LEADING)
 								.addComponent(icField)
 								.addComponent(dcField)
+								.addComponent(threshholdField)
 						)
 				)
 		);
@@ -109,6 +116,11 @@ public class EditCostPanel extends JPanel {
 						.addGap(4)
 						.addComponent(dcField)
 				)
+				.addGroup(layout.createParallelGroup(Alignment.BASELINE)
+						.addComponent(threshholdLable)
+						.addGap(4)
+						.addComponent(threshholdField)
+				)
 		);
 
 		this.setLayout(layout);
@@ -124,6 +136,8 @@ public class EditCostPanel extends JPanel {
 		return dcField.getValueAsDouble();
 	}
 
+	public double getThreshold() {return threshholdField.getValueAsDouble();}
+
 	public ColumnMapper getColumnMapper() {
 		return columnMapper;
 	}
diff --git a/src/main/java/de/hhu/ba/yoshikoWrapper/swing/components/MainPanel.java b/src/main/java/de/hhu/ba/yoshikoWrapper/swing/components/MainPanel.java
index 190eab5..a6eeb5e 100644
--- a/src/main/java/de/hhu/ba/yoshikoWrapper/swing/components/MainPanel.java
+++ b/src/main/java/de/hhu/ba/yoshikoWrapper/swing/components/MainPanel.java
@@ -23,6 +23,7 @@ package de.hhu.ba.yoshikoWrapper.swing.components;
 
 import static javax.swing.GroupLayout.DEFAULT_SIZE;
 import static javax.swing.GroupLayout.PREFERRED_SIZE;
+import static javax.swing.JOptionPane.showMessageDialog;
 
 import java.awt.Component;
 import java.awt.Dialog.ModalExclusionType;
@@ -49,7 +50,6 @@ import javax.swing.ScrollPaneConstants;
 
 import de.hhu.ba.yoshikoWrapper.taskFactories.CommandTaskFactory;
 import de.hhu.ba.yoshikoWrapper.taskFactories.YoshikoCommand;
-import de.hhu.ba.yoshikoWrapper.tasks.AlgorithmTask;
 import org.cytoscape.application.swing.CytoPanelComponent;
 import org.cytoscape.application.swing.CytoPanelName;
 import org.cytoscape.model.CyNetwork;
@@ -59,12 +59,9 @@ import org.cytoscape.work.TaskIterator;
 import de.hhu.ba.yoshikoWrapper.core.CyCore;
 import de.hhu.ba.yoshikoWrapper.core.LocalizationManager;
 import de.hhu.ba.yoshikoWrapper.core.ParameterSet;
-import de.hhu.ba.yoshikoWrapper.cytoUtil.CommandExecutor;
 import de.hhu.ba.yoshikoWrapper.cytoUtil.GraphAnalyzer;
-import de.hhu.ba.yoshikoWrapper.help.HelpLinks;
 import de.hhu.ba.yoshikoWrapper.swing.GraphicsLoader;
 import de.hhu.ba.yoshikoWrapper.swing.SwingUtil;
-import org.cytoscape.work.TaskManager;
 
 /**This class describes the Swing Panel that the user interacts with in cytoscape
  *
@@ -93,6 +90,8 @@ public class MainPanel extends JPanel implements CytoPanelComponent {
 
 	private final JButton runButton;
 
+	public ParameterSet parameterSet;
+
 	/**
 	 * Main constructor, creates a new Panel and initializes subcomponents
 	 */
@@ -214,6 +213,8 @@ public class MainPanel extends JPanel implements CytoPanelComponent {
 
 			CyNetwork networkToBeProcessed = CyCore.cy.getCurrentNetwork();
 
+			parameterSet = fetchParameters(networkToBeProcessed);
+
 			//WARNINGS FOR FEATURES THAT ARE NOT RESEARCHED
 			//TODO: (Obviously) research!
 			if (GraphAnalyzer.isMultiGraph(networkToBeProcessed)) {
@@ -225,7 +226,14 @@ public class MainPanel extends JPanel implements CytoPanelComponent {
 				);
 			}
 
-
+			try {
+				double recommendedThreshold = GraphAnalyzer.recommendThreshold(networkToBeProcessed, parameterSet);
+				if (!(recommendedThreshold==0)) {
+					showMessageDialog(null, "The provided graph only consists of edges with \n positive weight and will likely not yield a good result. \n Adjusting the threshold might be necessary. \n"+recommendedThreshold+" might be a good Threshold" , "Threshold-Warning",JOptionPane.WARNING_MESSAGE);
+				}
+			}catch (Exception exception){
+				exception.printStackTrace();
+			}
 			//SWING BLACK MAGIC
 			Window noWindow = null;
 			JDialog statusWindow = new JDialog(noWindow);
@@ -239,6 +247,8 @@ public class MainPanel extends JPanel implements CytoPanelComponent {
 			CyCore.statusWindow = statusWindow;
 			//SWING BLACK MAGIC
 
+
+
 			CommandTaskFactory commandTaskFactory = new CommandTaskFactory(YoshikoCommand.PERFORM_ALGORITHM);
 			TaskIterator taskIterator = commandTaskFactory.createTaskIterator();
 
@@ -247,8 +257,6 @@ public class MainPanel extends JPanel implements CytoPanelComponent {
 			} catch (InterruptedException ex) {
 				ex.printStackTrace();
 			}
-
-			System.out.println();
 		}
 	};
 
@@ -263,6 +271,7 @@ public class MainPanel extends JPanel implements CytoPanelComponent {
 		ret.setWeightColumn(ecPanel.getWeightColumn());
 		ret.setPermanentColumn(ecPanel.getPermanentColumn());
 		ret.setForbiddenColumn(ecPanel.getForbiddenColumn());
+		ret.threshold = ecPanel.getThreshold();
 		ret.defaultInsertionCost = ecPanel.getDefaultInsertionCost();
 		ret.defaultDeletionCost = ecPanel.getDefaultDeletionCost();
 		ret.useHeuristic = opModePanel.useHeuristic();
diff --git a/src/main/java/de/hhu/ba/yoshikoWrapper/swing/components/ResultPanel.java b/src/main/java/de/hhu/ba/yoshikoWrapper/swing/components/ResultPanel.java
index 9d39b11..920b58d 100644
--- a/src/main/java/de/hhu/ba/yoshikoWrapper/swing/components/ResultPanel.java
+++ b/src/main/java/de/hhu/ba/yoshikoWrapper/swing/components/ResultPanel.java
@@ -31,18 +31,10 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Properties;
 
-import javax.swing.BoxLayout;
-import javax.swing.GroupLayout;
+import javax.swing.*;
 import javax.swing.GroupLayout.ParallelGroup;
 import javax.swing.GroupLayout.SequentialGroup;
-import javax.swing.Icon;
-import javax.swing.JButton;
-import javax.swing.JLabel;
-import javax.swing.JOptionPane;
-import javax.swing.JPanel;
-import javax.swing.JTabbedPane;
-import javax.swing.LayoutStyle;
-import javax.swing.SwingConstants;
+import javax.swing.event.ChangeListener;
 
 import org.cytoscape.application.swing.CytoPanelComponent;
 import org.cytoscape.application.swing.CytoPanelName;
@@ -275,5 +267,4 @@ NetworkAboutToBeDestroyedListener
 	public void handleEvent(AboutToRemoveEdgesEvent e) {
 		invalidateIfRelevant(e);
 	}
-
 }
diff --git a/src/main/java/de/hhu/ba/yoshikoWrapper/taskFactories/CommandTaskFactory.java b/src/main/java/de/hhu/ba/yoshikoWrapper/taskFactories/CommandTaskFactory.java
index 4d3135c..a4a294f 100644
--- a/src/main/java/de/hhu/ba/yoshikoWrapper/taskFactories/CommandTaskFactory.java
+++ b/src/main/java/de/hhu/ba/yoshikoWrapper/taskFactories/CommandTaskFactory.java
@@ -45,11 +45,7 @@ public class CommandTaskFactory implements TaskFactory{
 		}
 		else if (command == YoshikoCommand.PERFORM_ALGORITHM) {
 			return new TaskIterator(
-					new AlgorithmTask(
-							null,
-							CyCore.mainPanel.fetchParameters(CyCore.cy.getCurrentNetwork())
-							)
-					);
+					new AlgorithmTask(null, CyCore.mainPanel.parameterSet));
 		}
 		else return null; //TODO: Might be useful to generate an error/ throw an exception here as this should never be invoked
 	}
diff --git a/src/main/java/de/hhu/ba/yoshikoWrapper/tasks/AlgorithmTask.java b/src/main/java/de/hhu/ba/yoshikoWrapper/tasks/AlgorithmTask.java
index 934d74c..ea0f96d 100644
--- a/src/main/java/de/hhu/ba/yoshikoWrapper/tasks/AlgorithmTask.java
+++ b/src/main/java/de/hhu/ba/yoshikoWrapper/tasks/AlgorithmTask.java
@@ -112,7 +112,6 @@ public class AlgorithmTask extends AbstractTask {
 
 		//Generate solutionsPanel
 		resultPanel = new ResultPanel(result);
-
 		//Show solution panel
 		CyCore.registrar.registerService(resultPanel, CytoPanelComponent.class, new Properties());
 		//Focus solution panel
@@ -130,8 +129,7 @@ public class AlgorithmTask extends AbstractTask {
 					}
 				}
 			);
-		eastPanel.getThisComponent().revalidate();
-
+		//eastPanel.getThisComponent().revalidate();
 	}
 
 
diff --git a/src/main/java/de/hhu/ba/yoshikoWrapper/yoshikoAlgorithm/ClusteringAlgorithm.java b/src/main/java/de/hhu/ba/yoshikoWrapper/yoshikoAlgorithm/ClusteringAlgorithm.java
index 8078e78..8c9e467 100644
--- a/src/main/java/de/hhu/ba/yoshikoWrapper/yoshikoAlgorithm/ClusteringAlgorithm.java
+++ b/src/main/java/de/hhu/ba/yoshikoWrapper/yoshikoAlgorithm/ClusteringAlgorithm.java
@@ -437,7 +437,6 @@ public class ClusteringAlgorithm {
                         if (edgeArray[i][j].startingWeight < 0){
                             clusteringCost -= edgeArray[i][j].startingWeight;
                             System.out.println("Insert edge:("+i+","+ j+") with cost "+edgeArray[i][j].startingWeight);
-
                         }
                         edgeArray[i][j].startingWeight = 0;
                     }
diff --git a/src/main/java/de/hhu/ba/yoshikoWrapper/yoshikoAlgorithm/GraphTranslator.java b/src/main/java/de/hhu/ba/yoshikoWrapper/yoshikoAlgorithm/GraphTranslator.java
index 73fd93e..504d747 100644
--- a/src/main/java/de/hhu/ba/yoshikoWrapper/yoshikoAlgorithm/GraphTranslator.java
+++ b/src/main/java/de/hhu/ba/yoshikoWrapper/yoshikoAlgorithm/GraphTranslator.java
@@ -1,26 +1,43 @@
 package de.hhu.ba.yoshikoWrapper.yoshikoAlgorithm;
 
 import de.hhu.ba.yoshikoWrapper.core.CyCore;
+import de.hhu.ba.yoshikoWrapper.core.LocalizationManager;
 import de.hhu.ba.yoshikoWrapper.core.NetworkParsingException;
 import de.hhu.ba.yoshikoWrapper.core.ParameterSet;
+import de.hhu.ba.yoshikoWrapper.cytoUtil.GraphAnalyzer;
 import de.hhu.ba.yoshikoWrapper.cytoUtil.NodeMap;
 import de.hhu.ba.yoshikoWrapper.cytoUtil.StyleManager;
 import de.hhu.ba.yoshikoWrapper.graphModel.YoshikoCluster;
 import de.hhu.ba.yoshikoWrapper.graphModel.YoshikoSolution;
+import de.hhu.ba.yoshikoWrapper.swing.components.MainPanel;
 import org.cytoscape.model.*;
 import org.cytoscape.model.subnetwork.CyRootNetwork;
 import org.cytoscape.model.subnetwork.CySubNetwork;
 import org.cytoscape.view.layout.CyLayoutAlgorithm;
 import org.cytoscape.view.model.CyNetworkView;
 
+import javax.swing.*;
+import java.awt.*;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
 import java.util.*;
+import java.util.List;
+
+import static javax.swing.JOptionPane.*;
 
 public final class GraphTranslator {
     private CyNetwork network;
     private ParameterSet parameterSet;
 
+    private boolean containsOnlyPositiveWeigths;
+    private double maxWeight;
+    private double minWeight;
+
     private double deletionCostDefault;
     private double insertionCostDefault;
+    private double threshold;
 
     CyColumn weightColumn;
 
@@ -34,13 +51,19 @@ public final class GraphTranslator {
         this.weightColumn = parameterSet.getWeightColumn();
         this.deletionCostDefault = parameterSet.defaultDeletionCost;
         this.insertionCostDefault = parameterSet.defaultInsertionCost;
+        this.threshold = parameterSet.threshold;
 
         this.nodeMap = new HashMap<>();
+        this.containsOnlyPositiveWeigths = true;
     }
 
     public YoshikoEdge[][] translateGraph() throws NetworkParsingException {
+        containsOnlyPositiveWeigths = true;
         this.makeGraph();
         this.makeGraphComplete();
+        parameterSet.containsOnlyPositiveEdges = containsOnlyPositiveWeigths;
+        parameterSet.recomendetTreshold = (minWeight + maxWeight)/2;
+
          return edgeArray;
     }
 
@@ -67,6 +90,10 @@ public final class GraphTranslator {
 
             double weight;
             weight = extractValue(e);
+            weight -= threshold;
+            if (weight < 0){
+                containsOnlyPositiveWeigths = false;
+            }
             YoshikoEdge yoshikoEdge = new YoshikoEdge(e.getSUID(), weight, u, v);
 
            edgeArray[yoshikoEdge.source][yoshikoEdge.target]= yoshikoEdge;
@@ -77,7 +104,7 @@ public final class GraphTranslator {
         for (int i = 1; i < edgeArray.length; i++){
             for (int j = 0; j < i; j++){
                 if (edgeArray[i][j] == null){
-                    YoshikoEdge yoshikoEdge = new YoshikoEdge(-1, insertionCostDefault, i, j);
+                    YoshikoEdge yoshikoEdge = new YoshikoEdge(-1, insertionCostDefault-threshold, i, j);
                     edgeArray[i][j] = yoshikoEdge;
                 }
             }
@@ -153,4 +180,42 @@ public final class GraphTranslator {
         }
     }
 
+    public void writeClusters(List<List<Integer>> clusters, int k) {
+        FileWriter fileWriter = null;
+        BufferedWriter bufferedWriter = null;
+
+        String s = network.getRow(network).get(CyNetwork.NAME, String.class);
+
+        s = s.substring(0, s.indexOf("."));
+
+        if (k < 0) {
+            s = s + "yoshikoClustering";
+        } else {
+            s = s+ "k-Clustering";
+        }
+
+        try {
+            File file = new File("C:\\Users\\User\\Desktop\\relevantClustEval\\optimalThreshold\\"+s);
+            file.createNewFile();
+            fileWriter = new FileWriter(file);
+            bufferedWriter = new BufferedWriter(fileWriter);
+            for (int i = 0; i < clusters.size(); i++) {
+                List<Integer> cluster = clusters.get(i);
+                for (Integer nodeId : cluster) {
+                    bufferedWriter.write(network.getRow(nodeMap.get(nodeId)).get(CyNetwork.NAME, String.class) + " " + i + "\n");
+                }
+            }
+            bufferedWriter.close();
+            fileWriter.close();
+        } catch (IOException e) {
+            e.printStackTrace();
+        } finally {
+            try {
+                bufferedWriter.close();
+                fileWriter.close();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+    }
 }
diff --git a/src/main/java/de/hhu/ba/yoshikoWrapper/yoshikoAlgorithm/YoshikoAlgoritmController.java b/src/main/java/de/hhu/ba/yoshikoWrapper/yoshikoAlgorithm/YoshikoAlgoritmController.java
index e08a1de..58a1833 100644
--- a/src/main/java/de/hhu/ba/yoshikoWrapper/yoshikoAlgorithm/YoshikoAlgoritmController.java
+++ b/src/main/java/de/hhu/ba/yoshikoWrapper/yoshikoAlgorithm/YoshikoAlgoritmController.java
@@ -43,6 +43,7 @@ public class YoshikoAlgoritmController {
         result.addSolution(solution);
 
         taskMonitor.setStatusMessage("Processing Clusters");
+        translator.writeClusters(clusters, k);
         translator.transateClusters(clusters, solution);
     }
 }
\ No newline at end of file
-- 
GitLab