#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 } }