blob: 645cad9b0efd32b65680c66b45e5a00729e68128 [file] [log] [blame]
package org.eclipse.stem.analysis.automaticexperiment.ui;
import java.util.ArrayList;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.Platform;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.stem.analysis.ErrorFunction;
import org.eclipse.stem.analysis.automaticexperiment.AutomaticExperiment;
import org.eclipse.stem.analysis.automaticexperiment.AutomaticexperimentFactory;
import org.eclipse.stem.analysis.automaticexperiment.ModifiableParameter;
import org.eclipse.stem.analysis.automaticexperiment.OptimizerAlgorithm;
import org.eclipse.stem.analysis.automaticexperiment.views.Messages;
import org.eclipse.stem.core.common.Identifiable;
import org.eclipse.stem.core.common.impl.IdentifiableImpl;
import org.eclipse.stem.core.scenario.Scenario;
import org.eclipse.stem.core.scenario.impl.ScenarioImpl;
import org.eclipse.stem.ui.Activator;
import org.eclipse.stem.ui.widgets.IdentifiablePickerDialog;
import org.eclipse.stem.ui.widgets.ParameterPickerDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.DirectoryDialog;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Text;
public class AutomaticExperimentCompositeEditor extends AlgorithmCompositeEditor {
Text maxItersText;
Text referenceDataText;
Text baseScenarioText;
Combo errorFunctionCombo;
Text startValText;
Text stepValText;
Text minValText;
Text maxValText;
Text toleranceText;
Table table;
boolean reInit = true;
ArrayList<Identifiable> identifiableList = new ArrayList<Identifiable>();
ArrayList<EAttribute> attributeList = new ArrayList<EAttribute>();
ArrayList<Double>minList = new ArrayList<Double>();
ArrayList<Double>maxList = new ArrayList<Double>();
ArrayList<Double>startList = new ArrayList<Double>();
ArrayList<Double>stepList = new ArrayList<Double>();
int currentTableIndex;
Scenario baseScenario;
String errorMessage;
public AutomaticExperimentCompositeEditor(Composite parent, int style, final ModifyListener projectValidator, final IProject project) {
super(parent, style);
// Fill in the rest here
final GridLayout gridLayout = new GridLayout();
gridLayout.numColumns = 3;
setLayout(gridLayout);
Label maxItersLabel = new Label(this, SWT.NONE);
maxItersLabel.setText(Messages.getString("NM.MAXITERS"));
GridData gridData = new GridData();
gridData.horizontalSpan = 1;
maxItersLabel.setLayoutData(gridData);
maxItersText = new Text(this, SWT.NONE);
maxItersText.setText("-1");
GridData gridData2 = new GridData();
gridData2.horizontalSpan = 2;
gridData2.grabExcessHorizontalSpace = true;
gridData2.horizontalAlignment = SWT.FILL;
maxItersText.setLayoutData(gridData2);
maxItersText.addModifyListener(projectValidator);
Label refDataLabel = new Label(this, SWT.NONE);
refDataLabel.setText(Messages.getString("NM.REFERENCE"));
GridData gridData3 = new GridData();
gridData3.horizontalSpan = 1;
refDataLabel.setLayoutData(gridData3);
referenceDataText = new Text(this, SWT.NONE);
referenceDataText.setText("");
GridData gridData4 = new GridData();
gridData4.horizontalSpan = 1;
gridData4.grabExcessHorizontalSpace = true;
gridData4.horizontalAlignment = SWT.FILL;
referenceDataText.setLayoutData(gridData4);
referenceDataText.addModifyListener(projectValidator);
Button pickRefereceButton = new Button(this, SWT.NONE);
pickRefereceButton.setText(Messages.getString("NM.REFPICKFOLDER"));
GridData gridData5 = new GridData();
gridData5.horizontalSpan = 1;
pickRefereceButton.setLayoutData(gridData5);
final Shell shell = this.getShell();
pickRefereceButton.addSelectionListener(new SelectionListener() {
public void widgetSelected(SelectionEvent e) {
final DirectoryDialog dd = new DirectoryDialog(shell,
SWT.OPEN | SWT.SINGLE);
dd.setText(Messages.getString("NM.REFFOLDERTITLE")); //$NON-NLS-1$
String selected = dd.open();
if(selected != null) referenceDataText.setText(selected);
}
public void widgetDefaultSelected(SelectionEvent e) {
}
});
Label baseScenarioLabel = new Label(this, SWT.NONE);
baseScenarioLabel.setText(Messages.getString("NM.BASESCENARIO"));
GridData gridData6 = new GridData();
gridData6.horizontalSpan = 1;
baseScenarioLabel.setLayoutData(gridData6);
baseScenarioText = new Text(this, SWT.NONE);
baseScenarioText.setText("");
GridData gridData7 = new GridData();
gridData7.horizontalSpan = 1;
gridData7.grabExcessHorizontalSpace = true;
gridData7.horizontalAlignment = SWT.FILL;
baseScenarioText.setLayoutData(gridData7);
baseScenarioText.setEditable(false);
baseScenarioText.addModifyListener(projectValidator);
Button pickScenarioButton = new Button(this, SWT.NONE);
pickScenarioButton.setText(Messages.getString("NM.SELECTSCENARIO"));
GridData gridData8 = new GridData();
gridData8.horizontalSpan = 1;
pickScenarioButton.setLayoutData(gridData8);
pickScenarioButton.addSelectionListener(new SelectionListener() {
public void widgetSelected(SelectionEvent e) {
IdentifiablePickerDialog ppDialog = new IdentifiablePickerDialog(AutomaticExperimentCompositeEditor.this.getShell(), SWT.NONE, Messages.getString("NM.PICKSCENARIO"), project, ScenarioImpl.class);
Object ret = ppDialog.open();
if(ret != null) {
baseScenario = (Scenario)ret;
baseScenarioText.setText(baseScenario.getURI().toString());
}
}
public void widgetDefaultSelected(SelectionEvent e) {
// TODO Auto-generated method stub
}
});
Label errorFunctionLabel = new Label(this, SWT.NONE);
errorFunctionLabel.setText(Messages.getString("NM.ERRORFUNCTION"));
GridData gridData9 = new GridData();
gridData9.horizontalSpan = 1;
baseScenarioLabel.setLayoutData(gridData9);
errorFunctionCombo = new Combo(this, SWT.NONE);
initializeErrorFunctionCombo();
GridData gridData10 = new GridData();
gridData10.horizontalSpan = 2;
gridData10.grabExcessHorizontalSpace = true;
gridData10.horizontalAlignment = SWT.FILL;
errorFunctionCombo.setLayoutData(gridData10);
Label reInitLabel = new Label(this, SWT.NONE);
reInitLabel.setText(Messages.getString("NM.REINITLABEL"));
GridData gridDataRI = new GridData();
gridDataRI.horizontalSpan = 1;
reInitLabel.setLayoutData(gridDataRI);
Composite radioComposite = new Composite(this, SWT.BORDER);
FillLayout fillLayout = new FillLayout();
fillLayout.type = SWT.HORIZONTAL;
radioComposite.setLayout(fillLayout);
final Button falseButton = new Button(radioComposite, SWT.RADIO);
falseButton.setText(Messages.getString("NM.NO"));//$NON-NLS-1$
Button trueButton = new Button(radioComposite, SWT.RADIO);
trueButton.setText(Messages.getString("NM.YES"));//$NON-NLS-1$
trueButton.setSelection(true);
falseButton.setSelection(false);
Listener listener = new Listener() {
public void handleEvent(Event event) {
if (event.widget == falseButton) {
reInit = !falseButton.getSelection();
}
}
};
// these are radio buttons so we only need to add the listener to one of them.
falseButton.addListener(SWT.Selection, listener);
final GridData cGD = new GridData();
cGD.grabExcessHorizontalSpace = true;
cGD.horizontalAlignment = SWT.FILL;
cGD.horizontalSpan = 2;
radioComposite.setLayoutData(cGD);
Label toleranceTabel = new Label(this, SWT.NONE);
toleranceTabel.setText(Messages.getString("NM.TOLERANCE"));
GridData tolGD = new GridData();
tolGD.horizontalSpan = 1;
toleranceTabel.setLayoutData(tolGD);
toleranceText = new Text(this, SWT.NONE);
toleranceText.setText("1E-9");
GridData tol2GD = new GridData();
tol2GD.horizontalSpan = 2;
tol2GD.grabExcessHorizontalSpace = true;
tol2GD.horizontalAlignment = SWT.FILL;
toleranceText.setLayoutData(tol2GD);
table = new Table(this, SWT.BORDER | SWT.SINGLE);
GridData gridData11 = new GridData();
gridData11.horizontalSpan = 1;
gridData11.grabExcessHorizontalSpace = true;
gridData11.horizontalAlignment = SWT.FILL;
gridData11.grabExcessVerticalSpace = false;
table.setLayoutData(gridData11);
Composite startStepComp = new Composite(this, SWT.NONE);
GridLayout startLayout = new GridLayout();
startLayout.numColumns = 2;
startStepComp.setLayout(startLayout);
Label startLabel = new Label(startStepComp, SWT.NONE);
startLabel.setText(Messages.getString("NM.INITIAL"));
GridData gridData12 = new GridData();
gridData12.horizontalSpan=1;
startLabel.setLayoutData(gridData12);
Label stepLabel = new Label(startStepComp, SWT.NONE);
stepLabel.setText(Messages.getString("NM.STEP"));
GridData gridData13 = new GridData();
gridData13.horizontalSpan=1;
stepLabel.setLayoutData(gridData13);
startValText = new Text(startStepComp, SWT.NONE);
GridData gridData14 = new GridData();
gridData13.horizontalSpan = 1;
startValText.setLayoutData(gridData14);
startValText.addModifyListener(projectValidator);
startValText.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent e) {
if(currentTableIndex == -1) return;
String txt = startValText.getText();
double d = 0.0;
try {
d = Double.parseDouble(txt);
} catch(NumberFormatException nfe) {
// Ignore, the validator will report the error
}
startList.set(currentTableIndex, d);
}
});
stepValText = new Text(startStepComp, SWT.NONE);
GridData gridData15 = new GridData();
gridData15.horizontalSpan = 1;
stepValText.setLayoutData(gridData15);
stepValText.addModifyListener(projectValidator);
stepValText.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent e) {
if(currentTableIndex == -1) return;
String txt = stepValText.getText();
double d = 0.0;
try {
d = Double.parseDouble(txt);
} catch(NumberFormatException nfe) {
// Ignore, the validator will report the error
}
stepList.set(currentTableIndex, d);
}
});
Composite minMaxComp = new Composite(this, SWT.NONE);
GridLayout minMaxLayout = new GridLayout();
minMaxLayout.numColumns = 2;
minMaxComp.setLayout(startLayout);
Label minLabel = new Label(minMaxComp, SWT.NONE);
minLabel.setText(Messages.getString("NM.MIN"));
GridData gridData16 = new GridData();
gridData16.horizontalSpan=1;
minLabel.setLayoutData(gridData12);
Label maxLabel = new Label(minMaxComp, SWT.NONE);
maxLabel.setText(Messages.getString("NM.MAX"));
GridData gridData17 = new GridData();
gridData17.horizontalSpan=1;
maxLabel.setLayoutData(gridData17);
minValText = new Text(minMaxComp, SWT.NONE);
GridData gridData18 = new GridData();
gridData18.horizontalSpan = 1;
minValText.setLayoutData(gridData18);
minValText.addModifyListener(projectValidator);
minValText.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent e) {
if(currentTableIndex == -1) return;
String txt = minValText.getText();
double d = 0.0;
try {
d = Double.parseDouble(txt);
} catch(NumberFormatException nfe) {
// Ignore, the validator will report the error
}
minList.set(currentTableIndex, d);
}
});
maxValText = new Text(minMaxComp, SWT.NONE);
GridData gridData19 = new GridData();
gridData19.horizontalSpan = 1;
maxValText.setLayoutData(gridData19);
maxValText.addModifyListener(projectValidator);
maxValText.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent e) {
if(currentTableIndex == -1) return;
String txt = maxValText.getText();
double d = 0.0;
try {
d = Double.parseDouble(txt);
} catch(NumberFormatException nfe) {
// Ignore, the validator will report the error
}
maxList.set(currentTableIndex, d);
}
});
minValText.setEnabled(false);
maxValText.setEnabled(false);
startValText.setEnabled(false);
stepValText.setEnabled(false);
Composite plusminusbuttons = new Composite(this, SWT.NONE);
GridLayout gridLayout2 = new GridLayout();
gridLayout2.numColumns = 2;
plusminusbuttons.setLayout(gridLayout2);
GridData gridData20 = new GridData();
gridData20.horizontalSpan = 1;
gridData20.grabExcessHorizontalSpace = true;
gridData20.horizontalAlignment = SWT.FILL;
plusminusbuttons.setLayoutData(gridData20);
Button plusButton = new Button(plusminusbuttons, SWT.NONE);
plusButton.setText(Messages.getString("NM.PLUS"));
GridData gridData21 = new GridData();
gridData21.horizontalSpan = 1;
plusButton.setLayoutData(gridData21);
final Button minusButton = new Button(plusminusbuttons, SWT.NONE);
minusButton.setText(Messages.getString("NM.MINUS"));
GridData gridData22 = new GridData();
gridData21.horizontalSpan = 1;
minusButton.setLayoutData(gridData22);
minusButton.setEnabled(false);
table.addSelectionListener(new SelectionListener() {
public void widgetSelected(SelectionEvent e) {
currentTableIndex = table.getSelectionIndex();
if(currentTableIndex > -1) {
minValText.setText(minList.get(currentTableIndex)+"");
maxValText.setText(maxList.get(currentTableIndex)+"");
startValText.setText(startList.get(currentTableIndex)+"");
stepValText.setText(stepList.get(currentTableIndex)+"");
minValText.setEnabled(true);
maxValText.setEnabled(true);
startValText.setEnabled(true);
stepValText.setEnabled(true);
minusButton.setEnabled(true);
} else {
minValText.setText("");
maxValText.setText("");
startValText.setText("");
stepValText.setText("");
minValText.setEnabled(false);
maxValText.setEnabled(false);
startValText.setEnabled(false);
stepValText.setEnabled(false);
}
}
public void widgetDefaultSelected(SelectionEvent e) {
// TODO Auto-generated method stub
}
});
plusButton.addSelectionListener(new SelectionListener() {
public void widgetSelected(SelectionEvent e) {
ParameterPickerDialog ppDialog = new ParameterPickerDialog(AutomaticExperimentCompositeEditor.this.getShell(), SWT.NONE, Messages.getString("NM.PICKPARAM"), project, IdentifiableImpl.class);
Object [] ret = ppDialog.open();
if(ret != null) {
Identifiable id = (Identifiable)ret[0];
EAttribute attr = (EAttribute)ret[1];
identifiableList.add(id);
attributeList.add(attr);
TableItem newRow= new TableItem(table, SWT.NONE);
newRow.setText(attr.getName()+" ("+id.getURI().lastSegment()+")");
minList.add(0.0);
maxList.add(1.0);
startList.add(0.5);
stepList.add(0.1);
projectValidator.modifyText(null);//
}
}
public void widgetDefaultSelected(SelectionEvent e) {
// TODO Auto-generated method stub
}
});
minusButton.addSelectionListener(new SelectionListener() {
public void widgetSelected(SelectionEvent e) {
if(currentTableIndex > -1) {
table.remove(currentTableIndex);
minList.remove(currentTableIndex);
maxList.remove(currentTableIndex);
startList.remove(currentTableIndex);
stepList.remove(currentTableIndex);
currentTableIndex = table.getSelectionIndex();
minValText.setText("");
maxValText.setText("");
startValText.setText("");
stepValText.setText("");
if(minList.size() == 0) {
minusButton.setEnabled(false);
minValText.setEnabled(false);
maxValText.setEnabled(false);
startValText.setEnabled(false);
stepValText.setEnabled(false);
}
}
}
public void widgetDefaultSelected(SelectionEvent e) {
// TODO Auto-generated method stub
}
});
}
private ErrorFunction[] errorFunctions;
private void initializeErrorFunctionCombo() {
final IExtensionRegistry registry = Platform.getExtensionRegistry();
final IConfigurationElement[] errorFunctionsConfigElements = registry
.getConfigurationElementsFor(org.eclipse.stem.analysis.Constants.ID_ERRORFUNCTION_EXTENSION_POINT);
final java.util.List<ErrorFunction> temp = new ArrayList<ErrorFunction>();
errorFunctions = new ErrorFunction[errorFunctionsConfigElements.length];
for (int i = 0; i < errorFunctionsConfigElements.length; i++) {
final IConfigurationElement element = errorFunctionsConfigElements[i];
if (element.getName().equals(org.eclipse.stem.analysis.Constants.ERRORFUNCTION_ELEMENT)) {
// Yes
try {
temp.add((ErrorFunction) element
.createExecutableExtension("class")); //$NON-NLS-1$
} catch (final CoreException e) {
Activator.logError(
Messages.getString("Unable to instantiate extension point "+element), e); //$NON-NLS-1$
}
} // if
} // for each configuration element
errorFunctions = temp.toArray(new ErrorFunction[] {});
for(int i=0;i<errorFunctions.length;++i)
errorFunctionCombo.add(errorFunctions[i].eClass().getName());
errorFunctionCombo.select(0);
}
@Override
public boolean validate() {
boolean retValue = true;
double minVal=0, maxVal=1, startVal=0.5, stepVal=0.1; // valid set of values, just in case the text boxes aren't enabled yet.
errorMessage = "";
if(retValue) {
if(startValText.isEnabled()) {
String val = startValText.getText();
retValue = checkDouble(val);
if(!retValue) errorMessage = Messages.getString("NM.BADSTART");
else startVal = Double.parseDouble(val);
}
}
if(retValue) {
if(stepValText.isEnabled()) {
String val = stepValText.getText();
retValue = checkDoubleNonZero(val);
if(!retValue) errorMessage = Messages.getString("NM.BADSTEP");
else stepVal = Double.parseDouble(val);
}
}
if(retValue) {
if(minValText.isEnabled()) {
String val = minValText.getText();
retValue = checkDouble(val);
if(!retValue) errorMessage = Messages.getString("NM.BADMIN");
else minVal = Double.parseDouble(val);
}
}
if(retValue) {
if(maxValText.isEnabled()) {
String val = maxValText.getText();
retValue = checkDouble(val);
if(!retValue) errorMessage = Messages.getString("NM.BADMAX");
else maxVal = Double.parseDouble(val);
}
}
if(retValue)
if(minVal >maxVal) {
errorMessage = Messages.getString("NM.BADMINMAX");
retValue = false;
}
if(retValue)
if(maxItersText.isEnabled()) {
String val = maxItersText.getText();
retValue = checkIntegerMinValue(val, -1);
if(!retValue) errorMessage = Messages.getString("NM.BADMAXITERS");
}
if(retValue)
if(referenceDataText.getText() == null || referenceDataText.getText().trim().equals("")) {
errorMessage = Messages.getString("NM.BADREFERENCE");
retValue = false;
}
if(retValue)
if(baseScenario == null) {
errorMessage = Messages.getString("NM.BADBASESCENARIO");
retValue = false;
}
if(retValue)
if(table.getItemCount() == 0) {
errorMessage = Messages.getString("NM.ATLEASTONEPARAM");
retValue = false;
}
if(retValue)
if(toleranceText.isEnabled()) {
retValue = checkDoublePositiveNonZero(toleranceText.getText());
}
return retValue;
}
@Override
public String getErrorMessage() {
return errorMessage;
}
private boolean checkDouble(String d) {
boolean retValue = true;
try {
Double.parseDouble(d);
} catch(Exception e) {
retValue = false;
}
return retValue;
}
@SuppressWarnings("unused")
private boolean checkDoubleNonZero(String d) {
boolean retValue = true;
try {
double _d = Double.parseDouble(d);
if(_d == 0.0) retValue = false;
} catch(Exception e) {
retValue = false;
}
return retValue;
}
private boolean checkIntegerMinValue(String i, int min) {
boolean retValue = true;
try {
int _i = Integer.parseInt(i);
if(_i < min) retValue = false;
} catch(Exception e) {
retValue = false;
}
return retValue;
}
private boolean checkDoublePositiveNonZero(String d) {
boolean retValue = true;
try {
double _d = Double.parseDouble(d);
if(_d < 0.0) retValue = false;
} catch(Exception e) {
retValue = false;
}
return retValue;
}
@Override
public OptimizerAlgorithm createAlgorithm() {
AutomaticExperiment autoExperiment = AutomaticexperimentFactory.eINSTANCE.createAutomaticExperiment();
autoExperiment.setBaseScenario(baseScenario);
int ind = errorFunctionCombo.getSelectionIndex();
if(ind == -1) ind = 0; // grab first one
autoExperiment.setErrorFunc(errorFunctions[ind]);
autoExperiment.setMaximumNumberOfIterations(Integer.parseInt(maxItersText.getText()));
autoExperiment.setReferanceDataDir(referenceDataText.getText()); // ToDO: Use platform independent method
autoExperiment.setReInit(reInit);
autoExperiment.setTolerance(Double.parseDouble(toleranceText.getText()));
int n=0;
for(Identifiable ident :identifiableList) {
ModifiableParameter param = AutomaticexperimentFactory.eINSTANCE.createModifiableParameter();
param.setTargetURI(ident.getURI());
param.setFeatureName(attributeList.get(n).getName());
param.setInitialValue(startList.get(n));
param.setStep(stepList.get(n));
param.setLowerBound(minList.get(n));
param.setUpperBound(maxList.get(n));
autoExperiment.getParameters().add(param);
++n;
}
return autoExperiment;
}
}