Skip to content
Snippets Groups Projects
Commit 8fea1b05 authored by Philipp Spohr's avatar Philipp Spohr
Browse files

Added support for auto config of reduction rules

parent 147092ef
No related branches found
No related tags found
No related merge requests found
Showing
with 270 additions and 99 deletions
......@@ -22,5 +22,7 @@ public class ParameterSet {
public boolean useHeuristic;
public int solCount;
public boolean disableMultiThreading;
/**Describes whether auto configuration of the reduction rules is to be used. Overrides the bit mask.**/
public boolean suggestReduction;
}
......@@ -2,10 +2,19 @@ package de.hhu.ba.yoshikoWrapper.cytoUtil;
import java.util.List;
import org.cytoscape.model.CyColumn;
import org.cytoscape.model.CyEdge;
import org.cytoscape.model.CyNetwork;
import org.cytoscape.model.CyRow;
import org.slf4j.Logger;
import de.hhu.ba.yoshikoWrapper.logging.YoshikoLogger;
public class GraphAnalyzer {
private static Logger logger = YoshikoLogger.getInstance().getLogger();
public static boolean isMultiGraph(CyNetwork net) {
//TODO: Better algorithm?
......@@ -47,4 +56,87 @@ public class GraphAnalyzer {
}
return false;
}
/**
* Generates a fitting bitmask by choosing the reduction rules that appear to be the best choice based on current research
* @param containsRealValues
* @param heuristic
* @return
*/
public static String suggestReductionRules(boolean containsRealValues, boolean heuristic) {
//TODO: Maybe also choose SNR Factor?
//TODO: More research, identify good rules
boolean useCRule = false,useCCRule= false,useACRule= false,useHERule= false,usePDRRule= false,useSNRule = false;
String ret = "";
//First of all: We don't choose any rules when in heuristic mode
if (!heuristic) {
//We check if the graph contains real weights
if (!containsRealValues) {
useCRule = true;
useCCRule = true;
useACRule = true;
useHERule = true;
}
usePDRRule = true;
useSNRule = true;
}
ret += (useCRule ? "1" : "0");
ret += (useCCRule ? "1" : "0");
ret += (useACRule ? "1" : "0");
ret += (useHERule ? "1" : "0");
ret += (usePDRRule ? "1" : "0");
ret += (useSNRule ? "1" : "0");
//logger.info("Suggesting the following reduction-rules bitmask: "+ret);
System.out.println("Suggesting the following reduction-rules bitmask: "+ret);
return ret;
}
public static boolean containsRealValues(
CyNetwork net,
CyColumn weightColumn,
CyColumn permanentColumn,
CyColumn forbiddenColumn,
double defaultInsertionCost,
double defaultDeletionCost)
{
//Simple checks: Deletion and Insertion Costs
if (defaultInsertionCost % 1 != 0 || defaultDeletionCost % 1 != 0) {
return true;
}
if (net != null){
//Fetch edges
List<CyEdge> edges = net.getEdgeList();
//Loop over edges
for (CyEdge e : edges) {
//Fetch entry and check if it exists
CyRow edgeEntry = net.getRow(e);
//Check if there is a weight column defined, else skip
if (weightColumn != null){
//Check if the column contains an entry for the respective edge
//It is possible, that there are missing entries
if (edgeEntry.get(weightColumn.getName(), weightColumn.getType()) != null){
if (weightColumn.getType() == Double.class) {
double weight = edgeEntry.get(weightColumn.getName(), Double.class);
if (weight%1!=0) {
return true;
}
}
}
}
}
}
return false;
}
}
......@@ -44,12 +44,12 @@ public class EditCostPanel extends JPanel {
private final JLabel icLabel;
private final JLabel dcLabel;
private final HelpButton helpButton;
//private final HelpButton helpButton;
public EditCostPanel() {
//Initialize components
helpButton = new HelpButton();
//helpButton = new HelpButton();
columnMapper = new ColumnMapper();
......@@ -66,7 +66,7 @@ public class EditCostPanel extends JPanel {
//Add components
SwingUtil.addAll(this,icLabel,icField);
SwingUtil.addAll(this,dcLabel,dcField);
SwingUtil.addAll(helpButton);
//SwingUtil.addAll(helpButton);
SwingUtil.addAll(this,columnMapper);
......@@ -74,7 +74,7 @@ public class EditCostPanel extends JPanel {
GroupLayout layout = new GroupLayout(this);
layout.setHorizontalGroup(layout.createParallelGroup()
.addComponent(helpButton,Alignment.TRAILING)
//.addComponent(helpButton,Alignment.TRAILING)
.addComponent(columnMapper)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(Alignment.LEADING)
......@@ -90,7 +90,7 @@ public class EditCostPanel extends JPanel {
);
layout.setVerticalGroup(layout.createSequentialGroup()
.addComponent(helpButton)
//.addComponent(helpButton)
.addComponent(columnMapper)
.addGroup(layout.createParallelGroup(Alignment.BASELINE)
.addComponent(icLabel)
......
......@@ -58,7 +58,9 @@ 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.core.YoshikoLoader;
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.LibraryPanelFactory;
import de.hhu.ba.yoshikoWrapper.swing.SwingUtil;
......@@ -117,7 +119,7 @@ public class MainPanel extends JPanel implements CytoPanelComponent {
@Override
public void actionPerformed(ActionEvent e) {
//CommandExecutorTaskFactory fac;
CommandExecutor.executeCommand("cybrowser", "show",HelpLinks.mainInfo , null);
}
});
......@@ -312,7 +314,7 @@ public class MainPanel extends JPanel implements CytoPanelComponent {
AbstractTask yoshiko = new AlgorithmTask(
popupLevel,
networkToBeProcessed,
fetchParameter()
fetchParameters(networkToBeProcessed)
);
/**
* Don't queue multiple runs at once because that will get messy
......@@ -340,7 +342,7 @@ public class MainPanel extends JPanel implements CytoPanelComponent {
* Fetches all the parameters from the various swing components and packs them into a neat abstract wrapper class
* @return The currently selected parameter wrapped in a ParameterSet
*/
private ParameterSet fetchParameter() {
private ParameterSet fetchParameters(CyNetwork net) {
ParameterSet ret = new ParameterSet();
ret.timeLimit = opModePanel.getTimeLimit();
ret.weightColumn = ecPanel.getWeightColumn();
......@@ -348,11 +350,12 @@ public class MainPanel extends JPanel implements CytoPanelComponent {
ret.forbiddenColumn = ecPanel.getForbiddenColumn();
ret.defaultInsertionCost = ecPanel.getDefaultInsertionCost();
ret.defaultDeletionCost = ecPanel.getDefaultDeletionCost();
ret.useHeuristic = opModePanel.useHeuristic();
ret.reductionRulesBitMask = reductionRulesChooser.getBitMask();
ret.suggestReduction = reductionRulesChooser.useAutoConfig();
ret.snrMultFactor = reductionRulesChooser.getMultFactor();
ret.useTriangleCuts = opModePanel.useTriangleCuts();
ret.usePartitionCuts = opModePanel.usePartitionCuts();
ret.useHeuristic = opModePanel.useHeuristic();
ret.solCount = opModePanel.getSolCount();
ret.disableMultiThreading = opModePanel.isMultiThreadingDisabled();
return ret;
......
......@@ -25,12 +25,16 @@ import static javax.swing.GroupLayout.DEFAULT_SIZE;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import javax.swing.BoxLayout;
import javax.swing.GroupLayout;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.SwingConstants;
import javax.swing.GroupLayout.Alignment;
import de.hhu.ba.yoshikoWrapper.core.LocalizationManager;
......@@ -39,6 +43,10 @@ import de.hhu.ba.yoshikoWrapper.swing.SwingUtil;
@SuppressWarnings("serial")
public class ReductionRulesChooser extends JPanel{
private final JCheckBox useAutoConfig;
private final JSeparator separator;
private final JCheckBox useCRule;
private final JCheckBox useCCRule;
private final JCheckBox useACRule;
......@@ -54,24 +62,34 @@ public class ReductionRulesChooser extends JPanel{
public ReductionRulesChooser() {
//Initialize subcomponents
useAutoConfig = new JCheckBox(LocalizationManager.get("autoConfig"));
useAutoConfig.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
enableRuleSelection(e.getStateChange()== ItemEvent.DESELECTED ? true : false);
}
});
separator = new JSeparator(SwingConstants.HORIZONTAL);
//TODO: Localization
useCRule = new JCheckBox("Use Clique Rule");
useCCRule = new JCheckBox("Use Critical-Clique Rule");
useACRule = new JCheckBox("Use Almost-Clique Rule");
useHERule = new JCheckBox("Use Heavy-Edge 3 in 1 Rule");
usePDRRule = new JCheckBox("Use Parameter Dependent Reduction Rule");
useSNRule = new JCheckBox("Use Similar Neighborhood Rule");
multFactor = new DoubleInputField(1, Double.POSITIVE_INFINITY);
multFactor.setText("1.0");
SNPanel = new JPanel();
SNPanel.setLayout(new BoxLayout(SNPanel,BoxLayout.X_AXIS));
SwingUtil.addAll(SNPanel,new JLabel(LocalizationManager.get("multFactor")),multFactor);
useSNRule.setSelected(true);
useCRule.setSelected(true);
useCCRule.setSelected(true);
useACRule.setSelected(true);
useHERule.setSelected(true);
usePDRRule.setSelected(true);
enableRuleSelection(false);
useAutoConfig.setSelected(true);
useSNRule.addActionListener(new ActionListener() {
@Override
......@@ -87,6 +105,8 @@ public class ReductionRulesChooser extends JPanel{
SwingUtil.addAll(this,
useAutoConfig,
separator,
useCRule,
useCCRule,
useACRule,
......@@ -102,6 +122,8 @@ public class ReductionRulesChooser extends JPanel{
layout.setAutoCreateGaps(true);
layout.setHorizontalGroup(layout.createParallelGroup(Alignment.LEADING,true)
.addComponent(useAutoConfig, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(separator, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(useCRule, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(useCCRule, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(useACRule, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE)
......@@ -112,6 +134,8 @@ public class ReductionRulesChooser extends JPanel{
);
layout.setVerticalGroup(layout.createSequentialGroup()
.addComponent(useAutoConfig, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(separator, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(useCRule, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(useCCRule, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(useACRule, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE)
......@@ -126,6 +150,17 @@ public class ReductionRulesChooser extends JPanel{
}
protected void enableRuleSelection(boolean enable) {
useCRule.setEnabled(enable);
useCCRule.setEnabled(enable);
useACRule.setEnabled(enable);
useHERule.setEnabled(enable);
usePDRRule.setEnabled(enable);
useSNRule.setEnabled(enable);
multFactor.setEnabled(enable);
}
/** Creates a 6 Bit bitmask representing the currently selected choice of reduction rules.
* @return
*/
......@@ -140,6 +175,10 @@ public class ReductionRulesChooser extends JPanel{
return ret;
}
public boolean useAutoConfig() {
return useAutoConfig.isSelected();
}
public double getMultFactor() {
if (useSNRule.isSelected()) {
return multFactor.getValueAsDouble();
......
......@@ -51,7 +51,7 @@ import de.hhu.ba.yoshikoWrapper.core.LocalizationManager;
import de.hhu.ba.yoshikoWrapper.graphModel.YoshikoCluster;
import de.hhu.ba.yoshikoWrapper.graphModel.YoshikoSolution;
import de.hhu.ba.yoshikoWrapper.swing.SwingUtil;
import de.hhu.ba.yoshikoWrapper.tasks.CreateClusterViews;
import de.hhu.ba.yoshikoWrapper.tasks.CreateClusterViewsTask;
import de.hhu.ba.yoshikoWrapper.tasks.CreateMetaGraphTask;
/**
* Swing Component, that represents one solution of a Yoshiko result and displays it
......@@ -149,7 +149,7 @@ public class SolutionTab extends JPanel {
}
CyCore.dialogTaskManager.execute(
new TaskIterator(1,
new CreateClusterViews(
new CreateClusterViewsTask(
selectedClusters
)
)
......
......@@ -3,7 +3,9 @@ package de.hhu.ba.yoshikoWrapper.taskFactories;
import org.cytoscape.work.TaskFactory;
import org.cytoscape.work.TaskIterator;
import de.hhu.ba.yoshikoWrapper.core.ParameterSet;
import de.hhu.ba.yoshikoWrapper.tasks.AlgorithmTask;
import de.hhu.ba.yoshikoWrapper.tasks.CreateClusterViewsTask;
public class CommandTaskFactory implements TaskFactory{
......@@ -21,7 +23,11 @@ public class CommandTaskFactory implements TaskFactory{
public TaskIterator createTaskIterator() {
//We simply switch between the possible commands
if (command == YoshikoCommand.CREATE_CLUSTER_VIEW) {
return null;
return new TaskIterator(
new CreateClusterViewsTask(
null
)
);
}
else if (command == YoshikoCommand.CREATE_META_GRAPH) {
return null;
......@@ -31,7 +37,7 @@ public class CommandTaskFactory implements TaskFactory{
new AlgorithmTask(
null,
null,
null
new ParameterSet()
)
);
}
......
......@@ -32,6 +32,7 @@ import org.cytoscape.model.CyNetwork;
import org.cytoscape.model.CyNode;
import org.cytoscape.work.AbstractTask;
import org.cytoscape.work.ContainsTunables;
import org.cytoscape.work.ObservableTask;
import org.cytoscape.work.TaskMonitor;
import org.cytoscape.work.Tunable;
import org.slf4j.Logger;
......@@ -41,6 +42,7 @@ import de.hhu.ba.yoshikoWrapper.core.LocalizationManager;
import de.hhu.ba.yoshikoWrapper.core.NetworkParser;
import de.hhu.ba.yoshikoWrapper.core.ParameterSet;
import de.hhu.ba.yoshikoWrapper.core.StatusInformer;
import de.hhu.ba.yoshikoWrapper.cytoUtil.GraphAnalyzer;
import de.hhu.ba.yoshikoWrapper.cytoUtil.NodeMap;
import de.hhu.ba.yoshikoWrapper.graphModel.YoshikoCluster;
import de.hhu.ba.yoshikoWrapper.graphModel.YoshikoResult;
......@@ -54,7 +56,7 @@ import de.hhu.ba.yoshikoWrapper.swig.LibraryInterface;
import de.hhu.ba.yoshikoWrapper.swing.components.ResultPanel;
public class AlgorithmTask extends AbstractTask {
public class AlgorithmTask extends AbstractTask implements ObservableTask {
//Constants
private static final String SOLUTION_COLUMN_PREFIX = "yoshikoSolution_"; //TODO: Make customizable?
......@@ -77,12 +79,15 @@ public class AlgorithmTask extends AbstractTask {
public CyNetwork net;
//Temps, pointing to and need to be freed in C++
private LibraryInput input;
private ClusterEditingSolutions result;
private CoreAlgorithm ca;
private LibraryInput c_input;
private ClusterEditingSolutions c_result;
private CoreAlgorithm c_algorithm;
private ResultPanel resultPanel;
private YoshikoResult result;
/**
* Default constructor, creates a new AlgorithmTask
* @param statusWindow The Window in which the status-bar is to be shown, can be null
......@@ -111,7 +116,7 @@ public class AlgorithmTask extends AbstractTask {
//Get current network
if (net == null) {
logger.warn("CoreAlgorithm called on a net that is NULL!");
throw new Exception("CoreAlgorithm called on a net that is NULL!");
throw new Exception("CoreAlgorithm called on a net that is NULL!"); //TODO: Localize
}
//Set time limit
......@@ -127,8 +132,8 @@ public class AlgorithmTask extends AbstractTask {
NodeMap nodeMap = new NodeMap(net);
taskMonitor.setProgress(0.1);
//Generate an input instance from the network
input = NetworkParser.parseNetwork(
//Generate an c_input instance from the network
c_input = NetworkParser.parseNetwork(
net,
nodeMap,
parameterSet.weightColumn,
......@@ -138,11 +143,24 @@ public class AlgorithmTask extends AbstractTask {
);
taskMonitor.setProgress(0.2);
boolean containsRealValues = GraphAnalyzer.containsRealValues(
net,
parameterSet.weightColumn,
parameterSet.permanentColumn,
parameterSet.forbiddenColumn,
parameterSet.defaultInsertionCost,
parameterSet.defaultDeletionCost);
//Suggest reduction rules
if (parameterSet.suggestReduction) {
parameterSet.reductionRulesBitMask = GraphAnalyzer.suggestReductionRules(containsRealValues, parameterSet.useHeuristic);
}
//Set the default value for insertion cost
input.setDefaultInsertionCost(parameterSet.defaultInsertionCost);
c_input.setDefaultInsertionCost(parameterSet.defaultInsertionCost);
//Call Yoshiko <<< Algorithm is performed here
ca = LibraryInterface.getRun(input,
c_algorithm = LibraryInterface.getRun(c_input,
parameterSet.solCount,
parameterSet.reductionRulesBitMask,
parameterSet.snrMultFactor,
......@@ -152,26 +170,26 @@ public class AlgorithmTask extends AbstractTask {
);
ca.registerCplexInformer(new StatusInformer(statusWindow,taskMonitor));
c_algorithm.registerCplexInformer(new StatusInformer(statusWindow,taskMonitor));
result = ca.run();
c_result = c_algorithm.run();
taskMonitor.setProgress(0.9);
checkForInvalidSolutions(result);
checkForInvalidSolutions(c_result);
long numberOfSolutions = result.getNumberOfSolutions();
long numberOfSolutions = c_result.getNumberOfSolutions();
taskMonitor.setStatusMessage("Found: "+numberOfSolutions+" solutions!"); //TODO: Localize
YoshikoResult yoshikoResult = new YoshikoResult(net,result.getFlags());
result = new YoshikoResult(net,c_result.getFlags());
//Loop over (multiple) solutions
for (long i=0;i<numberOfSolutions;i++) {
taskMonitor.setStatusMessage("Processing solution "+(i+1)+" of "+numberOfSolutions);
YoshikoSolution solution = new YoshikoSolution(yoshikoResult,i);
YoshikoSolution solution = new YoshikoSolution(result,i);
String columnName = SOLUTION_COLUMN_PREFIX+(i+1);
......@@ -179,7 +197,7 @@ public class AlgorithmTask extends AbstractTask {
net.getDefaultNodeTable().createColumn(columnName, String.class, false);
//Fetch number of clusters in the solution
long numberOfClusters = result.getNumberOfClusters(i);
long numberOfClusters = c_result.getNumberOfClusters(i);
//Loop over clusters
for (long k=0;k<numberOfClusters;k++) {
......@@ -189,7 +207,7 @@ public class AlgorithmTask extends AbstractTask {
taskMonitor.setStatusMessage("Processing clusters "+(k+1)+" of "+numberOfClusters);
IntVector clusterVector = result.getCluster(i, k);
IntVector clusterVector = c_result.getCluster(i, k);
long sizeOfCluster = clusterVector.size();
for (int l=0;l<sizeOfCluster;l++) { //Unsafe mismatch int long
......@@ -205,18 +223,18 @@ public class AlgorithmTask extends AbstractTask {
}
//Sort clusters by size, descending as the biggest clusters are usually the most relevant
solution.clusters.sort(YoshikoCluster.lessThanComparator);
//Register solution with result for further reference
yoshikoResult.addSolution(solution);
//Register solution with c_result for further reference
result.addSolution(solution);
}
taskMonitor.setProgress(0.99);
//At this point the C++ objects can be freed, in case that the algorithm terminates beforehand they need to be cleaned-up elsewhere
ca.delete();
input.delete();
result.delete();
c_algorithm.delete();
c_input.delete();
c_result.delete();
//Generate solutionsPanel
resultPanel = new ResultPanel(yoshikoResult);
resultPanel = new ResultPanel(result);
//Show solution panel
CyCore.registrar.registerService(resultPanel,CytoPanelComponent.class, new Properties());
......@@ -231,16 +249,16 @@ public class AlgorithmTask extends AbstractTask {
private void checkForInvalidSolutions(ClusterEditingSolutions result) throws Exception {
if (result == null) {
//There was no result object generated at all
//There was no c_result object generated at all
throw new Exception(LocalizationManager.get("noFeasible"));
}
if (result.getNumberOfSolutions() == 0) {
//The result object is empty
//The c_result object is empty
throw new Exception(LocalizationManager.get("noFeasible"));
}
if (result.getNumberOfSolutions() == 1) {
//The result doesn't contain any clusters
//The c_result doesn't contain any clusters
if (result.getNumberOfClusters(0) == 0) {
throw new Exception(LocalizationManager.get("noFeasible"));
}
......@@ -251,21 +269,30 @@ public class AlgorithmTask extends AbstractTask {
@Override
public void cancel() {
//Free C++ resources
if (ca != null) {
if (c_algorithm != null) {
System.out.println("Deleting CoreAlgorithm instance!");
ca.cancel();
ca.delete();
c_algorithm.cancel();
c_algorithm.delete();
}
if (input != null) {
input.delete();
if (c_input != null) {
c_input.delete();
}
if (result != null) {
result.delete();
if (c_result != null) {
c_result.delete();
}
//Delete (incomplete) result panel
//Delete (incomplete) c_result panel
if (resultPanel != null) {
resultPanel.deleteSolution();
}
super.cancel();
}
@Override
public <R> R getResults(Class<? extends R> type) {
//TODO:
if (type.equals(YoshikoResult.class)) {
return (R) (result!=null ? result : null);
}
return null;
}
}
......@@ -17,10 +17,10 @@ import de.hhu.ba.yoshikoWrapper.core.LocalizationManager;
import de.hhu.ba.yoshikoWrapper.cytoUtil.StyleManager;
import de.hhu.ba.yoshikoWrapper.graphModel.YoshikoCluster;
public class CreateClusterViews implements Task {
public class CreateClusterViewsTask implements Task {
@Tunable
public ArrayList<YoshikoCluster> clusters;
public ArrayList<YoshikoCluster> clusters; //TODO: Make Tunable, reference by ID?
private boolean isTerminated;
......@@ -35,7 +35,7 @@ public class CreateClusterViews implements Task {
*/
private ArrayList<CySubNetwork> initializedSubNetworks;
public CreateClusterViews(ArrayList<YoshikoCluster> clusters) {
public CreateClusterViewsTask(ArrayList<YoshikoCluster> clusters) {
this.clusters = clusters;
this.previousView = CyCore.cy.getCurrentNetworkView();
......
......@@ -26,6 +26,8 @@
about = Yoshiko Cytoscape App
aboutButton = About Yoshiko
aboutTitle = Yoshiko Plugin Info
autoConfig = Choose reduction rules automatically
clusters = Cluster
clusterFound = Clusters found:
clusterSize = Cluster Size:
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment