package net.certware.evidence.hugin.view.jobs; import il2.inf.map.MapSearch; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; import net.certware.core.ui.log.CertWareLog; import net.certware.evidence.hugin.view.Activator; import net.certware.evidence.hugin.view.ViewTree; import net.certware.evidence.hugin.view.preferences.PreferenceConstants; 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.Status; import org.eclipse.jface.preference.IPreferenceStore; import edu.ucla.belief.BeliefNetwork; import edu.ucla.belief.FiniteVariable; import edu.ucla.belief.Prune; import edu.ucla.belief.StateNotFoundException; import edu.ucla.belief.VariableImpl; import edu.ucla.belief.inference.JEngineGenerator; import edu.ucla.belief.inference.JoinTreeInferenceEngineImpl; import edu.ucla.belief.inference.JoinTreeSettings; import edu.ucla.belief.inference.map.ExactMap; import edu.ucla.belief.inference.map.InitializationMethod; import edu.ucla.belief.inference.map.MapRunner; import edu.ucla.belief.inference.map.SearchMethod; import edu.ucla.util.AbstractStringifier; /** * A job to perform the MAP estimate calculation. * @author mrb * @since 1.2.1 */ public class MapCalculationJob extends AbstractCalculationJob { /** * Constructor saves the network and view references. * @param jobName export job name for reporting * @param view view part reference */ public MapCalculationJob(String jobName, ViewTree view) { super(jobName,view); } /** * Production method for computations. * @param monitor progress monitor * @return CANCEL or OK */ @SuppressWarnings({ "unchecked", "rawtypes" }) public IStatus produce(IProgressMonitor monitor) { /** network name for messages */ String networkName = "undefined"; //$NON-NLS-1$ /** whether the exact calculation method is selected in preferences */ boolean exactCalculation = false; try { if ( initialNetwork == null ) { cancel(); CertWareLog.logWarning("Network not defined for calculation"); view.setWarningMessage(CANCEL_MSG); return Status.CANCEL_STATUS; } if ( nodes.isEmpty() ) { cancel(); CertWareLog.logWarning("No variable selections available for MAP calculation"); view.setWarningMessage(CANCEL_MSG); return Status.CANCEL_STATUS; } // network name from loaded file networkName = view.getSelectedFile().getName(); // initialize MAP variables from selections Set setMAPVariables = new HashSet(); for ( VariableNode v : nodes ) { if ( v.isSelected() ) { setMAPVariables.add( v.getNode() ); } } // initialize evidence from selections Map evidence = new HashMap(); for ( VariableNode vn : nodes ) { for ( VariableNodeState vns : vn.states ) { if ( vns.isSelected() ) { FiniteVariable fv = vn.getNode(); evidence.put( fv, fv.instance(vns.getStateName()) ); } } } // instantiation formatter VariableImpl.setStringifier( AbstractStringifier.VARIABLE_ID ); // fetch preferences IPreferenceStore ps = Activator.getDefault().getPreferenceStore(); String method = ps.getString(PreferenceConstants.P_MAP_COMPUTATION_METHOD); if ( method.equals(PreferenceConstants.P_MAP_COMPUTATION_METHOD_EXACT)) { exactCalculation = true; } monitor.worked(1); if ( monitor.isCanceled() ) { CertWareLog.logWarning(CANCEL_MSG); view.setWarningMessage(CANCEL_MSG); return Status.CANCEL_STATUS; } // perform exact or approximate calculation if ( exactCalculation ) { // time limit, zero is unlimited int timeoutsecs = ps.getInt(PreferenceConstants.P_MAP_TIMEOUT); timeoutsecs = Math.max(timeoutsecs, 0); // width barrier, zero is unlimited int widthbarrier = ps.getInt(PreferenceConstants.P_MAP_WIDTH_BARRIER); widthbarrier = Math.max(widthbarrier, 0); // non-sloppy version of engine MapSearch.MapInfo mapinfo = ExactMap.computeMap( initialNetwork, setMAPVariables, evidence, timeoutsecs, widthbarrier ); MapSearch.MapResult exactmapresult = (MapSearch.MapResult) mapinfo.results.iterator().next(); Map instantiation = exactmapresult.getConvertedInstatiation(); VariableImpl.setStringifier( AbstractStringifier.VARIABLE_ID ); monitor.worked(3); if ( monitor.isCanceled() ) { CertWareLog.logWarning(CANCEL_MSG); return Status.CANCEL_STATUS; } // clear marginals // TODO can compute these? clearMarginals(); //setMarginals(engine); // update results in view // job runs in a different thread, so ensure updates done in UI thread LinkedHashMap rows = new LinkedHashMap<String,String>(); rows.put("p(MAP,e)", getProbability(exactmapresult.score)); rows.put("p(MAP|e)", mapinfo.finished ? "Result is exact" : "Computation did not finish" ); rows.put("Instantiation", instantiation.toString()); rows.put("Search time", getSearchTime(exactmapresult.foundTime)); view.addResult(rows); } // exact else { // approximate int steps = ps.getInt(PreferenceConstants.P_MAP_SEARCH_STEPS); steps = Math.max(1, steps); // prune first BeliefNetwork networkUnpruned = initialNetwork; Set variablesUnpruned = setMAPVariables; Map evidenceUnpruned = evidence; Map oldToNew = new HashMap( networkUnpruned.size() ); Map newToOld = new HashMap( networkUnpruned.size() ); Set queryVarsPruned = new HashSet( variablesUnpruned.size() ); Map evidencePruned = new HashMap( evidenceUnpruned.size() ); BeliefNetwork networkPruned = Prune.prune( networkUnpruned, variablesUnpruned, evidenceUnpruned, oldToNew, newToOld, queryVarsPruned, evidencePruned ); BeliefNetwork beliefNetwork = networkPruned; setMAPVariables = queryVarsPruned; evidence = evidencePruned; monitor.worked(1); if ( monitor.isCanceled() ) { CertWareLog.logWarning(CANCEL_MSG); return Status.CANCEL_STATUS; } // create the inference engine JEngineGenerator generator = new JEngineGenerator(); JoinTreeInferenceEngineImpl engine = generator.makeJoinTreeInferenceEngineImpl( beliefNetwork, new JoinTreeSettings() ); // set evidence try { beliefNetwork.getEvidenceController().setObservations( evidencePruned ); } catch( StateNotFoundException e ) { CertWareLog.logError(String.format("%s %s","Calculating MAP",networkName), e); view.setWarningMessage(CANCEL_MSG); return Status.CANCEL_STATUS; }; monitor.worked(1); if ( monitor.isCanceled() ) { CertWareLog.logWarning(CANCEL_MSG); view.setWarningMessage(CANCEL_MSG); return Status.CANCEL_STATUS; } // engine settings SearchMethod searchmethod = PreferenceConstants.getSearchMethod(ps.getString(PreferenceConstants.P_MAP_SEARCH_METHOD)); InitializationMethod initializationmethod = PreferenceConstants.getInitializationMethod(ps.getString(PreferenceConstants.P_MAP_INITIALIZATION_METHOD)); // create MAP runner and invoke MapRunner maprunner = new MapRunner(); MapRunner.MapResult mapresult = maprunner.approximateMap( beliefNetwork, engine, setMAPVariables, evidence, searchmethod, initializationmethod, steps ); Map instantiation = mapresult.instantiation; monitor.worked(1); if ( monitor.isCanceled() ) { CertWareLog.logWarning(CANCEL_MSG); view.setWarningMessage(CANCEL_MSG); return Status.CANCEL_STATUS; } // clear marginals // TODO can compute these? // clearMarginals(); setMarginals(engine); // update results in view // job runs in a different thread, so ensure updates done in UI thread LinkedHashMap rows = new LinkedHashMap<String,String>(); rows.put("p(MAP,e)", getProbability(mapresult.score)); rows.put("p(MAP|e)", getEvidence( mapresult.score / engine.probability() )); rows.put("Instantiation", instantiation.toString()); rows.put("Initialization time", getInitializationTime(mapresult.initDurationMillisProfiled, mapresult.initDurationMillisElapsed)); rows.put("Initialization method", getInitialization(initializationmethod)); rows.put("Search time", getSearchTime(mapresult.searchDurationMillisProfiled, mapresult.searchDurationMillisElapsed)); rows.put("Search method", getSearch( searchmethod )); rows.put("Search steps", getSteps(steps)); view.addResult(rows); // clean up engine.die(); } // approximate } catch( Exception e ) { CertWareLog.logError(String.format("%s %s","MAP calculation for",networkName), e); return Status.CANCEL_STATUS; } String doneMessage = String.format("%s %s %s","MAP calculation for", networkName, "complete."); CertWareLog.logInfo( doneMessage ); return Status.OK_STATUS; } /** * Runs the generator job, reporting to the given progress monitor. * @param monitor progress monitor * @return CANCEL or OK status */ protected IStatus run(IProgressMonitor monitor) { int count = 5; monitor.beginTask("Computing MAP", count); IStatus rv = produce(monitor); if ( rv == Status.OK_STATUS ) { view.setInfoMessage("Completed MAP calculation"); monitor.done(); } return rv; } }