Commit c52b1d49 authored by Philipp Spohr's avatar Philipp Spohr
Browse files

More sophisticated informer system

Fixes for wrong meta-graph layout
Refactor
parent 8345651f
......@@ -55,8 +55,8 @@ import de.hhu.ba.yoshikoWrapper.core.LocalizationManager;
import de.hhu.ba.yoshikoWrapper.core.NetChangeListener;
import de.hhu.ba.yoshikoWrapper.core.YoshUtil;
import de.hhu.ba.yoshikoWrapper.core.YoshikoLoader;
import de.hhu.ba.yoshikoWrapper.gui.HintManager;
import de.hhu.ba.yoshikoWrapper.gui.MainPanel;
import de.hhu.ba.yoshikoWrapper.swing.HintManager;
import de.hhu.ba.yoshikoWrapper.swing.components.MainPanel;
/**
* Entry point for the application as required by the Cytoscape API
......
/*******************************************************************************
* Copyright (C) 2017 Philipp Spohr
*
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
......@@ -24,8 +24,6 @@ package de.hhu.ba.yoshikoWrapper.core;
import java.awt.Window;
import java.util.Properties;
import javax.swing.JOptionPane;
import org.cytoscape.application.swing.CytoPanel;
import org.cytoscape.application.swing.CytoPanelComponent;
import org.cytoscape.application.swing.CytoPanelName;
......@@ -39,19 +37,18 @@ import org.slf4j.Logger;
import de.hhu.ba.yoshikoWrapper.graphModel.YoshikoCluster;
import de.hhu.ba.yoshikoWrapper.graphModel.YoshikoResult;
import de.hhu.ba.yoshikoWrapper.graphModel.YoshikoSolution;
import de.hhu.ba.yoshikoWrapper.gui.ResultPanel;
import de.hhu.ba.yoshikoWrapper.logging.YoshikoLogger;
import de.hhu.ba.yoshikoWrapper.swig.ClusterEditingSolutions;
import de.hhu.ba.yoshikoWrapper.swig.CoreAlgorithm;
import de.hhu.ba.yoshikoWrapper.swig.CplexInformer;
import de.hhu.ba.yoshikoWrapper.swig.IntVector;
import de.hhu.ba.yoshikoWrapper.swig.LibraryInput;
import de.hhu.ba.yoshikoWrapper.swig.LibraryInterface;
import de.hhu.ba.yoshikoWrapper.swing.components.ResultPanel;
public class AlgorithmTask extends AbstractTask {
//Symbolic links
private static Logger logger = YoshikoLogger.getInstance().getLogger();
private Window statusWindow;
......@@ -59,19 +56,19 @@ public class AlgorithmTask extends AbstractTask {
//Parameters
private final ParameterSet parameterSet;
private final CyNetwork net;
//Temps, need to be freed in C++
private LibraryInput input;
private ClusterEditingSolutions result;
private CoreAlgorithm ca;
private ResultPanel resultPanel;
private ResultPanel resultPanel;
public AlgorithmTask(// <<< Too many variables here, some should be grouped later TODO:
Window statusWindow,
CyNetwork net,
ParameterSet parameterSet
)
)
{
this.statusWindow = statusWindow;
this.net = net;
......@@ -84,13 +81,13 @@ public class AlgorithmTask extends AbstractTask {
taskMonitor.setTitle(LocalizationManager.get("yoshTask"));
taskMonitor.setProgress(0.0);
//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!");
}
//Set time limit
LibraryInterface.setTimeLimit(parameterSet.timeLimit);
if (parameterSet.disableMultiThreading) {
......@@ -109,7 +106,7 @@ public class AlgorithmTask extends AbstractTask {
net,
nodeMap,
parameterSet.weightColumn,
parameterSet.permanentColumn,
parameterSet.permanentColumn,
parameterSet.forbiddenColumn,
parameterSet.defaultDeletionCost
);
......@@ -117,93 +114,66 @@ public class AlgorithmTask extends AbstractTask {
//Set the default value for insertion cost
input.setDefaultInsertionCost(parameterSet.defaultInsertionCost);
//Call Yoshiko <<< Algorithm is performed here
ca = LibraryInterface.getRun(input,
ca = LibraryInterface.getRun(input,
parameterSet.solCount,
parameterSet.reductionRulesBitMask,
parameterSet.snrMultFactor,
parameterSet.snrMultFactor,
parameterSet.usePartitionCuts,
parameterSet.useTriangleCuts,
parameterSet.useHeuristic
);
class CallbackHandler extends CplexInformer{
@Override
public boolean continueOnTimeout() {
try {
int result = JOptionPane.showConfirmDialog(
statusWindow,
LocalizationManager.get("continueTimeout"),
LocalizationManager.get("timeoutTitle"),
JOptionPane.YES_NO_OPTION,
JOptionPane.INFORMATION_MESSAGE
);
if (result == JOptionPane.YES_OPTION) {
return true;
}
return false;
}
catch(Exception e) {
e.printStackTrace();
return false;
}
}
@Override
public void updateGap(double gap) {
taskMonitor.setStatusMessage(LocalizationManager.get("currentGap")+": "+YoshUtil.twoDecimals.format(gap)+"%");
}
}
ca.registerCplexInformer(new CallbackHandler());
ca.registerCplexInformer(new StatusInformer(statusWindow,taskMonitor));
result = ca.run();
taskMonitor.setProgress(0.9);
checkForInvalidSolutions(result);
long numberOfSolutions = result.getNumberOfSolutions();
taskMonitor.setStatusMessage("Found: "+numberOfSolutions+" solutions!"); //TODO localize
YoshikoResult yoshikoResult = new YoshikoResult();
yoshikoResult.flags = result.getFlags();
System.out.print("ILP FLAG: "+yoshikoResult.flags.getIlpGenerated());
//Loop over (multiple) solutions
for (long i=0;i<numberOfSolutions;i++) {
taskMonitor.setStatusMessage("Processing solution "+(i+1)+" of "+numberOfSolutions);
YoshikoSolution solution = new YoshikoSolution(net);
String columnName = "YOSHIKO_SOLUTION_"+(i+1);
net.getDefaultNodeTable().deleteColumn(columnName);
net.getDefaultNodeTable().createColumn(columnName, String.class, false);
//Fetch number of clusters in the solution
long numberOfClusters = result.getNumberOfClusters(i);
//Loop over cluster
for (long k=0;k<numberOfClusters;k++) {
//Create java instance
YoshikoCluster cluster = new YoshikoCluster(k,net);
taskMonitor.setStatusMessage("Processing cluster "+(k+1)+" of "+numberOfClusters);
IntVector clusterVector = result.getCluster(i, k);
long sizeOfCluster = clusterVector.size();
for (int l=0;l<sizeOfCluster;l++) { //Unsafe mismatch int long
taskMonitor.setStatusMessage("Processing entry "+(l+1)+ " of "+sizeOfCluster);
int nodeID = clusterVector.get(l);
CyNode node = nodeMap.indexOf(nodeID); //<<< Another int/long conversion
cluster.addNode(node);
net.getRow(node).set(columnName, ""+(k+1)); //Add Cluster ID in table (Remove in final version?)
}
cluster.getSubNetwork();
......@@ -217,7 +187,7 @@ public class AlgorithmTask extends AbstractTask {
ca.delete();
input.delete();
result.delete();
//Generate solutionsPanel
resultPanel = new ResultPanel(yoshikoResult);
......@@ -230,13 +200,13 @@ public class AlgorithmTask extends AbstractTask {
eastPanel.setState(CytoPanelState.DOCK);
}
private void checkForInvalidSolutions(ClusterEditingSolutions result) throws Exception {
if (result == null) {
//There was no result object generated at all
throw new Exception(LocalizationManager.get("noFeasible"));
}
if (result.getNumberOfSolutions() == 0) {
//The result object is empty
throw new Exception(LocalizationManager.get("noFeasible"));
......@@ -247,7 +217,7 @@ public class AlgorithmTask extends AbstractTask {
throw new Exception(LocalizationManager.get("noFeasible"));
}
}
}
@Override
......
......@@ -34,7 +34,7 @@ import org.cytoscape.model.events.RemovedEdgesListener;
import org.cytoscape.session.events.SessionLoadedEvent;
import org.cytoscape.session.events.SessionLoadedListener;
import de.hhu.ba.yoshikoWrapper.gui.ColumnMapper;
import de.hhu.ba.yoshikoWrapper.swing.components.ColumnMapper;
public class NetChangeListener
implements //everything
......
package de.hhu.ba.yoshikoWrapper.core;
import java.awt.Window;
import javax.swing.JOptionPane;
import org.cytoscape.work.TaskMonitor;
import de.hhu.ba.yoshikoWrapper.swig.CplexInformer;
import de.hhu.ba.yoshikoWrapper.swig.YoshikoState;
import de.hhu.ba.yoshikoWrapper.swing.SwingUtil;
public class StatusInformer extends CplexInformer {
private final Window statusWindow;
private final TaskMonitor taskMonitor;
public StatusInformer(Window statusWindow, TaskMonitor taskMonitor) {
this.statusWindow = statusWindow;
this.taskMonitor = taskMonitor;
};
@Override
public boolean continueOnTimeout() {
try {
int result = JOptionPane.showConfirmDialog(
statusWindow,
LocalizationManager.get("continueTimeout"),
LocalizationManager.get("timeoutTitle"),
JOptionPane.YES_NO_OPTION,
JOptionPane.INFORMATION_MESSAGE
);
if (result == JOptionPane.YES_OPTION) {
return true;
}
return false;
}
catch(Exception e) {
e.printStackTrace();
return false;
}
}
@Override
public void updateStatus(YoshikoState state, double value) {
if (state == YoshikoState.SOLVING_ILP){
taskMonitor.setStatusMessage(LocalizationManager.get("currentGap")+": "+SwingUtil.twoDecimals.format(value)+"%");
}
}
@Override
public void updateStatus(YoshikoState state) {
//TODO: Might improve performance via HashMap but probably irrelevant
if (state == YoshikoState.REDUCTION_AC) {
taskMonitor.setStatusMessage(LocalizationManager.get("status_reductionAC"));
}
else if (state == YoshikoState.REDUCTION_CC) {
taskMonitor.setStatusMessage(LocalizationManager.get("status_reductionCC"));
}
else if (state == YoshikoState.REDUCTION_CR) {
taskMonitor.setStatusMessage(LocalizationManager.get("status_reductionCR"));
}
else if (state == YoshikoState.REDUCTION_HE) {
taskMonitor.setStatusMessage(LocalizationManager.get("status_reductionHE"));
}
else if (state == YoshikoState.REDUCTION_MR) {
taskMonitor.setStatusMessage(LocalizationManager.get("status_reductionMR"));
}
else if (state == YoshikoState.REDUCTION_PD) {
taskMonitor.setStatusMessage(LocalizationManager.get("status_reductionPD"));
}
else if (state == YoshikoState.REDUCTION_SN) {
taskMonitor.setStatusMessage(LocalizationManager.get("status_reductionSN"));
}
}
}
package de.hhu.ba.yoshikoWrapper.core;
import java.text.DecimalFormat;
import org.osgi.framework.Version;
public class YoshUtil {
final static DecimalFormat twoDecimals =new DecimalFormat("0.00");
public static Version version;
}
......@@ -22,19 +22,18 @@ public class StyleManager {
public static final double MAX_NODE_SIZE = 30.0;
private static void apply (CyNetworkView view, VisualStyle style) {
public static void style(CyNetworkView view, VisualStyle style) {
CyCore.visualMappingManager.setVisualStyle(style,view);
style.apply(view);
view.updateView();
}
public static void style(CyNetworkView view, VisualStyle style) {
apply(view,style);
}
public static void styleWithMapping(CyNetworkView view, VisualStyle style) {
style = CyCore.visualStyleFactory.createVisualStyle(style);
CyCore.visualMappingManager.setVisualStyle(style,view);
//Define style for solution
ContinuousMapping<Integer, Double> contMapNodes = (ContinuousMapping<Integer, Double>)CyCore.continuousMappingFactory.createVisualMappingFunction(
......@@ -81,7 +80,9 @@ public class StyleManager {
style.addVisualMappingFunction(contMapNodes);
style.addVisualMappingFunction(contMapEdges);
apply(view,style);
style.apply(view);
view.updateView();
}
......
......@@ -138,12 +138,12 @@ public class YoshikoCluster {
public void run(TaskMonitor taskMonitor) throws Exception {
taskMonitor.setStatusMessage("Generating cluster view for C:"+id);
StyleManager.style(view, CyCore.visualMappingManager.getCurrentVisualStyle());
view.setVisualProperty(NETWORK_WIDTH, new Double(width));
view.setVisualProperty(NETWORK_HEIGHT, new Double(height));
view.fitContent();
view.updateView();
StyleManager.style(view, CyCore.visualMappingManager.getCurrentVisualStyle());
RenderingEngine<CyNetwork> renderingEngine = CyCore.renderingEngineFactory.createRenderingEngine(label, view);
SwingUtilities.invokeLater(new Runnable() {
......
......@@ -32,6 +32,9 @@ import org.cytoscape.model.CyEdge.Type;
import org.cytoscape.model.subnetwork.CySubNetwork;
import org.cytoscape.view.layout.CyLayoutAlgorithm;
import org.cytoscape.view.model.CyNetworkView;
import org.cytoscape.work.Task;
import org.cytoscape.work.TaskIterator;
import org.cytoscape.work.TaskMonitor;
import de.hhu.ba.yoshikoWrapper.core.CyCore;
import de.hhu.ba.yoshikoWrapper.core.LocalizationManager;
......@@ -83,7 +86,6 @@ public class YoshikoSolution {
CyCore.networkManager.addNetwork(subnet);
//Create network view and register it
CyNetworkView subnetView = CyCore.networkViewFactory.createNetworkView(subnet);
CyCore.networkViewManager.addNetworkView(subnetView);
//layout cluster
CyCore.dialogTaskManager.execute(
layout.createTaskIterator(
......@@ -96,6 +98,8 @@ public class YoshikoSolution {
StyleManager.style(subnetView,CyCore.visualMappingManager.getCurrentVisualStyle());
CyCore.networkViewManager.addNetworkView(subnetView);
clusterNode.setNetworkPointer(subnet);
//Set node attributes
metaGraph.getRow(clusterNode).set("name", LocalizationManager.get("cluster")+" "+c.getID());
......@@ -132,24 +136,38 @@ public class YoshikoSolution {
}
CyNetworkView view = CyCore.networkViewFactory.createNetworkView(metaGraph);
//layout solution
CyCore.dialogTaskManager.execute(
layout.createTaskIterator(
view,
layout.getDefaultLayoutContext(),
CyLayoutAlgorithm.ALL_NODE_VIEWS,
null
)
//Layout and style solution
TaskIterator it = layout.createTaskIterator(
view,
layout.getDefaultLayoutContext(),
CyLayoutAlgorithm.ALL_NODE_VIEWS,
null
);
it.append(new Task() {
@Override
public void run(TaskMonitor taskMonitor) throws Exception {
StyleManager.styleWithMapping(view, CyCore.visualMappingManager.getCurrentVisualStyle());
}
@Override
public void cancel() {}
});
CyCore.dialogTaskManager.execute(
it
);
CyCore.networkManager.addNetwork(metaGraph);
CyCore.networkViewManager.addNetworkView(
view
);
StyleManager.styleWithMapping(view, CyCore.visualMappingManager.getCurrentVisualStyle());
view.updateView();
CyCore.cy.setCurrentNetworkView(view);
}
......
......@@ -4,7 +4,7 @@ import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
import de.hhu.ba.yoshikoWrapper.gui.EditCostPanel;
import de.hhu.ba.yoshikoWrapper.swing.components.EditCostPanel;
public final class HelpLinks {
......
......@@ -50,8 +50,12 @@ public class CplexInformer {
LibraryInterfaceJNI.CplexInformer_change_ownership(this, swigCPtr, true);
}
public void updateGap(double gap) {
if (getClass() == CplexInformer.class) LibraryInterfaceJNI.CplexInformer_updateGap(swigCPtr, this, gap); else LibraryInterfaceJNI.CplexInformer_updateGapSwigExplicitCplexInformer(swigCPtr, this, gap);
public void updateStatus(YoshikoState state) {
if (getClass() == CplexInformer.class) LibraryInterfaceJNI.CplexInformer_updateStatus__SWIG_0(swigCPtr, this, state.swigValue()); else LibraryInterfaceJNI.CplexInformer_updateStatusSwigExplicitCplexInformer__SWIG_0(swigCPtr, this, state.swigValue());
}
public void updateStatus(YoshikoState state, double value) {
if (getClass() == CplexInformer.class) LibraryInterfaceJNI.CplexInformer_updateStatus__SWIG_1(swigCPtr, this, state.swigValue(), value); else LibraryInterfaceJNI.CplexInformer_updateStatusSwigExplicitCplexInformer__SWIG_1(swigCPtr, this, state.swigValue(), value);
}
public boolean continueOnTimeout() {
......
......@@ -57,8 +57,10 @@ public class LibraryInterfaceJNI {
public final static native void LibraryInput_addEdge__SWIG_1(long jarg1, LibraryInput jarg1_, long jarg2, long jarg3, double jarg4, boolean jarg5, boolean jarg6);
public final static native void LibraryInput_setSize(long jarg1, LibraryInput jarg1_, long jarg2);
public final static native void LibraryInput_setDefaultInsertionCost(long jarg1, LibraryInput jarg1_, double jarg2);
public final static native void CplexInformer_updateGap(long jarg1, CplexInformer jarg1_, double jarg2);
public final static native void CplexInformer_updateGapSwigExplicitCplexInformer(long jarg1, CplexInformer jarg1_, double jarg2);
public final static native void CplexInformer_updateStatus__SWIG_0(long jarg1, CplexInformer jarg1_, int jarg2);
public final static native void CplexInformer_updateStatusSwigExplicitCplexInformer__SWIG_0(long jarg1, CplexInformer jarg1_, int jarg2);
public final static native void CplexInformer_updateStatus__SWIG_1(long jarg1, CplexInformer jarg1_, int jarg2, double jarg3);
public final static native void CplexInformer_updateStatusSwigExplicitCplexInformer__SWIG_1(long jarg1, CplexInformer jarg1_, int jarg2, double jarg3);
public final static native boolean CplexInformer_continueOnTimeout(long jarg1, CplexInformer jarg1_);
public final static native boolean CplexInformer_continueOnTimeoutSwigExplicitCplexInformer(long jarg1, CplexInformer jarg1_);
public final static native void delete_CplexInformer(long jarg1);
......@@ -75,8 +77,11 @@ public class LibraryInterfaceJNI {
public final static native void setVerbosity(int jarg1);
public final static native long getRun(long jarg1, LibraryInput jarg1_, int jarg2, String jarg3, double jarg4, boolean jarg5, boolean jarg6, boolean jarg7);
public static void SwigDirector_CplexInformer_updateGap(CplexInformer jself, double gap) {
jself.updateGap(gap);
public static void SwigDirector_CplexInformer_updateStatus__SWIG_0(CplexInformer jself, int state) {
jself.updateStatus(YoshikoState.swigToEnum(state));
}
public static void SwigDirector_CplexInformer_updateStatus__SWIG_1(CplexInformer jself, int state, double value) {
jself.updateStatus(YoshikoState.swigToEnum(state), value);
}
public static boolean SwigDirector_CplexInformer_continueOnTimeout(CplexInformer jself) {
return jself.continueOnTimeout();
......
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 3.0.8
*
* Do not make changes to this file unless you know what you are doing--modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
package de.hhu.ba.yoshikoWrapper.swig;
public final class YoshikoState {
public final static YoshikoState PARSING_INPUT = new YoshikoState("PARSING_INPUT", 0);
public final static YoshikoState REDUCTION_AC = new YoshikoState("REDUCTION_AC", 1);
public final static YoshikoState REDUCTION_CR = new YoshikoState("REDUCTION_CR", 2);
public final static YoshikoState REDUCTION_CC = new YoshikoState("REDUCTION_CC", 3);
public final static YoshikoState REDUCTION_PD = new YoshikoState("REDUCTION_PD", 4);
public final static YoshikoState REDUCTION_HE = new YoshikoState("REDUCTION_HE", 5);
public final static YoshikoState REDUCTION_MR = new YoshikoState("REDUCTION_MR", 6);
public final static YoshikoState REDUCTION_SN = new YoshikoState("REDUCTION_SN", 7);
public final static YoshikoState SOLVING_HEURISTIC = new YoshikoState("SOLVING_HEURISTIC", 8);
public final static YoshikoState SOLVING_ILP = new YoshikoState("SOLVING_ILP", 9);
public final static YoshikoState PROCESS_SOLUTION = new YoshikoState("PROCESS_SOLUTION", 10);
public final int swigValue() {
return swigValue;
}
public String toString() {
return swigName;
}
public static YoshikoState swigToEnum(int swigValue) {
if (swigValue < swigValues.length && swigValue >= 0 && swigValues[swigValue].swigValue == swigValue)
return swigValues[swigValue];
for (int i = 0; i < swigValues.length; i++)
if (swigValues[i].swigValue == swigValue)
return swigValues[i];
throw new IllegalArgumentException("No enum " + YoshikoState.class + " with value " + swigValue);
}
private YoshikoState(String swigName) {
this.swigName = swigName;
this.swigValue = swigNext++;
}
private YoshikoState(String swigName, int swigValue) {
this.swigName = swigName;
this.swigValue =