package net.certware.evidence.hugin.view.jobs;
import java.text.NumberFormat;
import java.util.List;
import net.certware.core.ui.CertWareUI;
import net.certware.core.ui.log.CertWareLog;
import net.certware.evidence.hugin.view.ViewTree;
import net.certware.evidence.hugin.view.tree.VariableNode;
import net.certware.evidence.hugin.view.tree.VariableNodeState;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.swt.widgets.Display;
import edu.ucla.belief.BeliefNetwork;
import edu.ucla.belief.InferenceEngine;
import edu.ucla.belief.Table;
import edu.ucla.belief.inference.map.InitializationMethod;
import edu.ucla.belief.inference.map.SearchMethod;
/**
* An abstract job template for inference engine calculations.
* @author mrb
* @since 1.2.1
*/
public abstract class AbstractCalculationJob extends Job
{
/** bail-out message */
protected final static String CANCEL_MSG = "Canceled calculation before completion";
/** network model */
protected final BeliefNetwork initialNetwork;
/** view for reporting and model access */
protected ViewTree view;
/** tree viewer nodes for selection access */
protected List<VariableNode> nodes;
/** maximum fraction formatting digits */
protected static final int MAX_DIGITS = 8;
/** minimum fraction formatting digits */
protected static final int MIN_DIGITS = 3;
/**
* Constructor saves the network and view references.
* @param jobName export job name for reporting
* @param view view part reference
*/
public AbstractCalculationJob(String jobName, ViewTree view) {
super(jobName);
assert(view != null);
this.view = view;
this.initialNetwork = view.getSelectedNetwork();
this.nodes = view.getVariableNodes();
}
/**
* Job family membership.
* @param family family ID, test against core CertWare ID
* @return true if ID matches, otherwise returns value from superclass
*/
public boolean belongsTo(final Object family) {
if (family.equals(CertWareUI.PLUGIN_ID)) {
return true;
}
return super.belongsTo(family);
}
/**
* Production method for computations.
* @param monitor progress monitor
* @return CANCEL or OK
*/
public abstract IStatus produce(IProgressMonitor monitor);
/**
* Runs the generator job, reporting to the given progress monitor.
* @param monitor progress monitor
* @return CANCEL or OK status
*/
protected abstract IStatus run(IProgressMonitor monitor);
/**
* Set the search display value.
* @param search method used in computation
*/
public String getSearch(final SearchMethod sm) {
return sm == SearchMethod.HILL ? "Hill Climbing" : "Taboo" ;
}
/**
* Set the search initialization display value.
* @param search initialization used in computation
*/
public String getInitialization(final InitializationMethod im) {
String s = "Random";
if ( im == InitializationMethod.MPE ) {
s = "MPE";
} else if ( im == InitializationMethod.SEQ ) {
s = "Sequential";
} else if ( im == InitializationMethod.ML ) {
s = "Maximum Likelihood";
}
return s;
}
/**
* Set the steps display value.
* @param i steps preference value used
*/
public String getSteps(final int i) {
String rv = "";
try {
final NumberFormat nf = NumberFormat.getIntegerInstance();
nf.setGroupingUsed(true);
rv = nf.format(i);
} catch( Exception e ) {
String message = String.format("%s %s","Formatting steps setting",e.toString());
view.setWarningMessage(message);
CertWareLog.logWarning(message);
}
return rv;
}
/**
* Set the search time result value. Provides both profiled (CPU) and elapsed times.
* @param profiled profiled time in milliseconds
* @param elapsed elapsed time in milliseconds
*/
public String getSearchTime(final double profiled, final double elapsed) {
final NumberFormat nf = NumberFormat.getNumberInstance();
nf.setGroupingUsed(true);
nf.setMaximumFractionDigits(MAX_DIGITS);
nf.setMinimumFractionDigits(MIN_DIGITS);
String rv = "";
try {
String profiledTime = String.format("%s %s",nf.format(profiled),"ms");
String elapsedTime = String.format("%s %s",nf.format(elapsed),"ms");
rv = String.format("%s CPU, %s elapsed",profiledTime,elapsedTime);
} catch( Exception e ) {
String message = String.format("%s %s","Formatting search time result",e.toString());
view.setWarningMessage(message);
CertWareLog.logWarning(message);
}
return rv;
}
/**
* Set the exact calculation time result value.
* @param elapsed elapsed time in milliseconds
*/
public String getSearchTime(final long elapsed) {
String rv = "";
try {
final NumberFormat nf = NumberFormat.getIntegerInstance();
nf.setGroupingUsed(true);
String elapsedTime = String.format("%s %s",nf.format(elapsed),"ms");
rv = String.format("%s elapsed",elapsedTime);
} catch( Exception e ) {
String message = String.format("%s %s","Formatting search time result",e.toString());
view.setWarningMessage(message);
CertWareLog.logWarning(message);
}
return rv;
}
/**
* Set the initialization time result value. Provides both profiled (CPU) and elapsed times.
* @param profiled profiled time in milliseconds
* @param elapsed elapsed time in milliseconds
*/
public String getInitializationTime(final double profiled, final double elapsed) {
String rv = "";
final NumberFormat nf = NumberFormat.getNumberInstance();
nf.setGroupingUsed(true);
nf.setMaximumFractionDigits(MAX_DIGITS);
nf.setMinimumFractionDigits(MIN_DIGITS);
try {
String profiledTime = String.format("%s %s",nf.format(profiled),"ms");
String elapsedTime = String.format("%s %s",nf.format(elapsed),"ms");
rv = String.format("%s CPU, %s elapsed",profiledTime,elapsedTime);
} catch( Exception e ) {
String message = String.format("%s %s","Formatting initialization time result",e.toString());
view.setWarningMessage(message);
CertWareLog.logWarning(message);
}
return rv;
}
/**
* Set the probability p(map,e) or p(mpe,e) result value.
* @param d new value
*/
public String getProbability(final double d) {
final NumberFormat nf = NumberFormat.getNumberInstance();
String rv = "";
try {
nf.setGroupingUsed(true);
nf.setMaximumFractionDigits(MAX_DIGITS);
nf.setMinimumFractionDigits(MIN_DIGITS);
rv = nf.format(d);
} catch( Exception e ) {
String message = String.format("%s %s","Formatting p(map,e) result",e.toString());
view.setWarningMessage(message);
CertWareLog.logWarning(message);
}
return rv;
}
/**
* Set the evidence p(map|e) result value.
* @param d new value
*/
public String getEvidence(final double d) {
final NumberFormat nf = NumberFormat.getNumberInstance();
String rv = "";
try {
nf.setGroupingUsed(true);
nf.setMaximumFractionDigits(MAX_DIGITS);
nf.setMinimumFractionDigits(MIN_DIGITS);
rv = nf.format(d);
} catch( Exception e ) {
String message = String.format("%s %s","Formatting p(map|e) result",e.toString());
view.setWarningMessage(message);
CertWareLog.logWarning(message);
}
return rv;
}
/**
* Sets marginal probability items to zero and refreshes the tree.
*/
public void clearMarginals() {
Display.getDefault().asyncExec(new Runnable(){
public void run() {
for ( VariableNode vn : nodes ) {
for ( VariableNodeState vns : vn.states ) {
vns.setMarginal(0.0);
view.getTreeViewer().refresh(vns);
}
}
}
});
}
/**
* Sets the marginal values in the model by copying them from the inference engine.
* @param engine inference engine source after calculations complete
*/
public void setMarginals(final InferenceEngine engine) {
if ( engine == null ) {
System.err.println("inference engine null for marginals calculation");
return;
}
Display.getDefault().asyncExec(new Runnable(){
public void run() {
try {
for ( VariableNode vn : nodes ) {
int index = 0;
Table table = engine.conditional( vn.getNode() );
if ( table == null ) {
System.err.println("table null for variable " + vn.getNode() );
continue;
}
for ( VariableNodeState vns : vn.states ) {
double m = table.getCP(index);
vns.setMarginal(m);
view.getTreeViewer().refresh(vns);
index++;
}
}
} catch( NullPointerException npe) {
CertWareLog.logWarning("Computation of marginal probabilities not available");
}
}
});
}
}