protected void ThreadMainScenariosInference()
{
while (true)
{
if (_scenariosThreadCancel)
{
break;
}
bool didWork = false;
List<ScenarioRecord> scenarios;
lock (_scenariosInternal)
{
scenarios = _scenariosInternal.ToList();
}
// For each scenario, refine the results.
foreach (var scenarioRecord in scenarios)
{
InferenceQuery inferenceQuery = scenarioRecord.Query;
// If more refinement is needed.
if (inferenceQuery.RefinementCount < this.InferenceTargetRefinement)
{
int nvariables = inferenceQuery.Network.Variables.Count;
int batchSize = InferenceStepBatchSizeVariable / nvariables;
if (batchSize < InferenceStepBatchSizeMinimum)
{
batchSize = InferenceStepBatchSizeMinimum;
}
inferenceQuery.RefineResults(batchSize);
didWork = true;
var resultsCopy = inferenceQuery.Results.ToDictionary(
kvp => kvp.Key,
kvp => kvp.Value);
scenarioRecord.Scenario.PosteriorMarginals = resultsCopy;
}
// If no more refinement is needed.
if (inferenceQuery.RefinementCount >= this.InferenceTargetRefinement
&& scenarioRecord.Scenario.InferenceState != ComputationState.Done)
{
scenarioRecord.Scenario.InferenceState = ComputationState.Done;
}
}
// Update comparison.
if (scenarios.Count == 2)
{
if (didWork || _comparisonOptionsDirty)
{
_comparisonOptionsDirty = false;
var comparisonMetric = this._comparisonMetric;
ScenarioComparison oldComparison = _scenariosComparison;
ScenarioComparison comparison = new ScenarioComparison();
comparison.Scenario1 = scenarios[0].Scenario;
comparison.Scenario2 = scenarios[1].Scenario;
comparison.ComparisonMetric = comparisonMetric;
var posteriors1 = comparison.Scenario1.PosteriorMarginals;
var posteriors2 = comparison.Scenario2.PosteriorMarginals;
List<Tuple<String, Double>> similarities = new List<Tuple<string, double>>();
foreach (string variableName in posteriors1.Keys)
{
var variableDist1 = posteriors1[variableName];
var variableDist2 = posteriors2[variableName];
double dissimilarity;
if (comparisonMetric == Model.ComparisonMetric.SymmetricKLDivergence)
{
dissimilarity = this.MeasureDissimilarityKL(variableDist1, variableDist2);
}
else if (comparisonMetric == Model.ComparisonMetric.ErrorSum)
{
dissimilarity = this.MeasureDissimilarityES(variableDist1, variableDist2);
}
else
{
Debug.Fail("Unexpected state.");
dissimilarity = 0;
}
similarities.Add(new Tuple<string, double>(variableName, dissimilarity));
}
// Put most different variables first in the list.
comparison.SignificantVariables
= similarities
.OrderByDescending(s => s.Item2)
.TakeFraction(this._comparisonResultsLevel)
.ToArray();
// Store in model.
this._scenariosComparison = comparison;
if (this.ComparisonResultsUpdated != null)
{
this.ComparisonResultsUpdated(comparison);
}
// Restart layout process.
IList<string> significantVariables
= comparison
.SignificantVariables
.Select(x => x.Item1)
.OrderBy(x => x)
.ToList();
if (oldComparison == null ||
oldComparison
.SignificantVariables
.Select(x => x.Item1)
.OrderBy(x => x)
.SequenceEqual(significantVariables) == false)
{
_networkLayoutInternal = new NetworkLayoutRecord(
_bayesianNetwork,
_networkLayout,
significantVariables,
NetworkLayoutOptions
);
}
// Done.
didWork = true;
}
}
else
{
_scenariosComparison = null;
}
if (_scenariosThreadCancel)
{
break;
}
if (!didWork)
{
Thread.Sleep(200);
}
else
{
// HACK: Gives UI some time to breath if we're updating inference results
// too often.
Thread.Sleep(50);
}
}
}