#region License Information
/* HeuristicLab
* Copyright (C) 2002-2016 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
*
* This file is part of HeuristicLab.
*
* HeuristicLab is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* HeuristicLab is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with HeuristicLab. If not, see .
*/
#endregion
using HeuristicLab.Common.Resources;
using HeuristicLab.Core;
using HeuristicLab.Data;
using HeuristicLab.MainForm;
using HeuristicLab.MainForm.WindowsForms;
using HeuristicLab.OptimizationExpertSystem.Common;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;
namespace HeuristicLab.OptimizationExpertSystem {
[View("Understanding Problem Instance")]
[Content(typeof(KnowledgeCenter), IsDefaultView = false)]
public sealed partial class UnderstandingProblemInstanceView : KnowledgeCenterViewBase {
private bool SuppressEvents { get; set; }
private readonly CheckedItemList characteristics;
public UnderstandingProblemInstanceView() {
InitializeComponent();
showCharacteristicsCheckBox.Text = string.Empty;
showCharacteristicsCheckBox.Image = VSImageLibrary.Properties;
updateProjectionButton.Text = string.Empty;
updateProjectionButton.Image = VSImageLibrary.Refresh;
characteristics = new CheckedItemList();
characteristics.CheckedItemsChanged += CharacteristicsOnCheckedItemsChanged;
characteristicsPanel.Controls.Add(new ViewHost() {
Dock = DockStyle.Fill,
Content = characteristics
});
}
protected override void OnContentChanged() {
base.OnContentChanged();
if (Content == null) {
problemInstancesView.Content = null;
} else {
problemInstancesView.Content = Content.ProblemInstances;
}
UpdateCharacteristics();
UpdateProjectionComboBox();
UpdateSizeComboBox();
UpdateColorComboBox();
}
protected override void SetEnabledStateOfControls() {
base.SetEnabledStateOfControls();
updateProjectionButton.Enabled = Content != null && characteristics.CheckedItems.Any();
}
#region Update Controls
private void UpdateCharacteristics() {
if (InvokeRequired) { Invoke((Action)UpdateCharacteristics); return; }
try {
SuppressEvents = true;
var @checked = new HashSet(characteristics.CheckedItems.Select(x => x.Value.Value));
characteristics.Clear();
if (Content == null) return;
if (@checked.Count == 0 && Content.ProblemInstances.ResultNames.Any(x => x.StartsWith("Characteristic.")))
@checked = new HashSet(Content.ProblemInstances.ResultNames.Where(x => x.StartsWith("Characteristic.")));
foreach (var c in Content.ProblemInstances.ResultNames) {
characteristics.Add(new StringValue(c), @checked.Contains(c));
}
} finally { SuppressEvents = false; }
}
private void UpdateProjectionComboBox() {
if (InvokeRequired) { Invoke((Action)UpdateProjectionComboBox); return; }
try {
SuppressEvents = true;
var selected = projectionComboBox.SelectedIndex >= 0 ? (string)projectionComboBox.SelectedItem : null;
projectionComboBox.Items.Clear();
foreach (var str in GetProjections()) {
projectionComboBox.Items.Add(str);
if (selected == str) projectionComboBox.SelectedItem = str;
}
if (selected == null && projectionComboBox.Items.Count > 0)
projectionComboBox.SelectedIndex = 0;
} finally { SuppressEvents = false; }
}
private void UpdateSizeComboBox() {
if (InvokeRequired) { Invoke((Action)UpdateSizeComboBox); return; }
try {
SuppressEvents = true;
var selected = sizeComboBox.SelectedIndex >= 0 ? (string)sizeComboBox.SelectedItem : null;
sizeComboBox.Items.Clear();
if (Content == null) return;
sizeComboBox.Items.Add(string.Empty);
foreach (var str in Content.ProblemInstances.ResultNames.Where(x => !(x.StartsWith("Projection.") && (x.EndsWith(".X") || x.EndsWith(".Y"))))) {
sizeComboBox.Items.Add(str);
if (selected == str) sizeComboBox.SelectedItem = str;
}
if (selected == null && sizeComboBox.Items.Count > 0)
sizeComboBox.SelectedIndex = 0;
} finally { SuppressEvents = false; }
}
private void UpdateColorComboBox() {
if (InvokeRequired) { Invoke((Action)UpdateColorComboBox); return; }
try {
SuppressEvents = true;
var selected = colorComboBox.SelectedIndex >= 0 ? (string)colorComboBox.SelectedItem : null;
colorComboBox.Items.Clear();
if (Content == null) return;
colorComboBox.Items.Add(string.Empty);
foreach (var str in Content.ProblemInstances.ResultNames.Where(x => x.StartsWith("Rank."))) {
colorComboBox.Items.Add(str);
if (selected == str) colorComboBox.SelectedItem = str;
}
if (selected == null && colorComboBox.Items.Count > 0)
colorComboBox.SelectedIndex = 0;
} finally { SuppressEvents = false; }
}
private void UpdateProjection() {
if (InvokeRequired) { Invoke((Action)UpdateProjection); return; }
var instancesSeries = instanceMapChart.Series["InstancesSeries"];
var currentInstanceSeries = instanceMapChart.Series["CurrentInstanceSeries"];
if (projectionComboBox.SelectedIndex < 0 || Content == null) {
instancesSeries.Points.Clear();
currentInstanceSeries.Points.Clear();
return;
}
var projection = (string)projectionComboBox.SelectedItem;
var size = sizeComboBox.SelectedIndex >= 0 ? (string)sizeComboBox.SelectedItem : string.Empty;
var color = colorComboBox.SelectedIndex >= 0 ? (string)colorComboBox.SelectedItem : string.Empty;
DoProjectProblemInstances(instancesSeries, currentInstanceSeries, projection, size, color, invPropCheckBox.Checked);
}
#endregion
#region Content Event Handlers
protected override void OnProblemChanged() {
base.OnProblemChanged();
SetEnabledStateOfControls();
}
protected override void OnProblemInstancesChanged() {
base.OnProblemInstancesChanged();
if (Content.ProblemInstances.UpdateOfRunsInProgress) return;
UpdateCharacteristics();
UpdateProjectionComboBox();
UpdateSizeComboBox();
UpdateColorComboBox();
UpdateProjection();
}
#endregion
#region Control Event Handlers
private void ProjectionComboBoxOnSelectedIndexChanged(object sender, EventArgs e) {
UpdateProjection();
}
private void SizeComboBoxOnSelectedIndexChanged(object sender, EventArgs e) {
UpdateProjection();
}
private void colorComboBox_SelectedIndexChanged(object sender, EventArgs e) {
UpdateProjection();
}
private void InvPropCheckBoxOnCheckedChanged(object sender, EventArgs e) {
UpdateProjection();
}
private void showCharacteristicsCheckBox_CheckedChanged(object sender, EventArgs e) {
mapSplitContainer.Panel2Collapsed = !showCharacteristicsCheckBox.Checked;
}
private void updateProjectionButton_Click(object sender, EventArgs e) {
Content.UpdateInstanceProjection(characteristics.CheckedItems.Select(x => x.Value.Value).ToArray());
}
#endregion
#region Other Event Handlers
private void CharacteristicsOnCheckedItemsChanged(object sender, EventArgs e) {
SetEnabledStateOfControls();
}
#endregion
#region Helper Classes and Methods
private IEnumerable GetProjections() {
if (Content == null) return new string[0];
return Content.ProblemInstances.ResultNames
.Where(x => Regex.IsMatch(x, "^Projection[.].*[.][XY]$"))
.Select(x => Regex.Match(x, "Projection[.](?.*)[.][XY]").Groups["g"].Value)
.Distinct();
}
private void DoProjectProblemInstances(Series instancesSeries, Series currentInstanceSeries, string projection, string size, string color, bool invProp) {
instancesSeries.Points.Clear();
currentInstanceSeries.Points.Clear();
double maxSize = 0, minSize = 0;
if (!string.IsNullOrEmpty(size)) {
var sizes = Content.ProblemInstances
.Where(x => x.Results.ContainsKey(size))
.Select(x => x.Results[size])
.Select(x => x is DoubleValue ? ((DoubleValue)x).Value : (x is IntValue ? ((IntValue)x).Value : double.NaN))
.Where(x => !double.IsNaN(x)).ToList();
if (sizes.Count > 0) {
maxSize = sizes.Max();
if (maxSize < 0) {
maxSize = 0;
minSize = sizes.Min();
} else {
minSize = sizes.Min();
}
}
}
foreach (var run in Content.ProblemInstances) {
var xKey = "Projection." + projection + ".X";
var yKey = "Projection." + projection + ".Y";
if (!run.Results.ContainsKey(xKey) || !run.Results.ContainsKey(yKey)
|| !(run.Results[xKey] is DoubleValue) || !(run.Results[yKey] is DoubleValue)) continue;
var x = ((DoubleValue)run.Results[xKey]).Value;
var y = ((DoubleValue)run.Results[yKey]).Value;
var dataPoint = new DataPoint(x, y) {
Label = run.Name,
};
IItem item;
if (maxSize > minSize && run.Results.TryGetValue(size, out item)) {
var dItem = item as DoubleValue;
if (dItem == null && item is IntValue) dItem = new DoubleValue(((IntValue)item).Value);
if (dItem != null) {
if (double.IsNaN(dItem.Value))
dataPoint.MarkerSize = 1;
else {
if (invProp) dataPoint.MarkerSize = (int)Math.Round(5 + 15 * (maxSize - dItem.Value) / (maxSize - minSize));
else dataPoint.MarkerSize = (int)Math.Round(5 + 15 * (dItem.Value - minSize) / (maxSize - minSize));
}
}
} else if (maxSize == minSize) {
dataPoint.MarkerSize = instancesSeries.MarkerSize;
} else dataPoint.MarkerSize = 1;
if (!string.IsNullOrEmpty(color)) {
if (run.Results.TryGetValue(color, out item)) {
var v = (int)(item is DoubleValue ? ((DoubleValue)item).Value : (item is IntValue ? ((IntValue)item).Value : int.MaxValue));
switch (v) {
case 0: dataPoint.MarkerColor = Color.Green; break;
case 1: dataPoint.MarkerColor = Color.LightSeaGreen; break;
case 2: dataPoint.MarkerColor = Color.CornflowerBlue; break;
case 3: dataPoint.MarkerColor = Color.PaleVioletRed; break;
case 4: dataPoint.MarkerColor = Color.IndianRed; break;
default: dataPoint.MarkerColor = Color.LightGray; break;
}
}
}
if (Content.IsCurrentInstance(run)) currentInstanceSeries.Points.Add(dataPoint);
else instancesSeries.Points.Add(dataPoint);
}
}
#endregion
}
}