/// <summary>
/// The find optimum hypothesis.
/// </summary>
/// <param name="observations">
/// The observations.
/// </param>
/// <param name="driftTubeLength">
/// The drift Tube Length.
/// </param>
/// <param name="massTarget">
/// The mass Target.
/// </param>
/// <param name="parameters">
/// The parameters.
/// </param>
/// <returns>
/// The <see cref="AssociationHypothesis"/>.
/// </returns>
/// <exception cref="NotImplementedException">
/// </exception>
public AssociationHypothesis FindOptimumHypothesis(IEnumerable<ObservedPeak> observations, double driftTubeLength, IImsTarget massTarget, CrossSectionSearchParameters parameters, int numberOfVoltageGroups)
{
observations = observations.ToList();
ObservationTransitionGraph<IonTransition> transitionGraph = new ObservationTransitionGraph<IonTransition>(observations, (a, b) => new IonTransition(a, b));
// Visualize the graph.
// transitionGraph.PlotGraph();
// Find all the possible combinotorial tracks
// IList<IsomerTrack> candidateTracks = this.FindAllReasonableTracks(transitionGraph, driftTubeLength, massTarget, parameters).ToList();
// Find the top N tracks using K shorestest path algorithm
IEnumerable<IEnumerable<IonTransition>> kShorestPaths = transitionGraph.PeakGraph.RankedShortestPathHoffmanPavley(t => 0 - Math.Log(t.TransitionProbability), transitionGraph.SourceVertex, transitionGraph.SinkVertex, this.maxTracks);
IEnumerable<IsomerTrack> candidateTracks = MinCostFlowIonTracker.ToTracks(kShorestPaths, parameters, numberOfVoltageGroups, parameters.RegressionSelection);
// filter paths
TrackFilter filter = new TrackFilter();
Predicate<IsomerTrack> trackPredicate = track => filter.IsTrackPossible(track, massTarget, parameters);
List<IsomerTrack> filteredTracks = candidateTracks.ToList().FindAll(trackPredicate);
// Select the top N tracks to proceed to next step.
var hypotheses = this.FindAllHypothesis(filteredTracks, observations).ToArray();
// Find the combination of tracks that produces the highest posterior probablity.
IOrderedEnumerable<AssociationHypothesis> sortedAssociationHypotheses = hypotheses.OrderByDescending(h => h.ProbabilityOfHypothesisGivenData);
return sortedAssociationHypotheses.FirstOrDefault();
}