Free cookie consent management tool by TermsFeed Policy Generator

source: branches/QAP/HeuristicLab.Problems.QuadraticAssignment.Views/3.3/QAPView.cs @ 5825

Last change on this file since 5825 was 5820, checked in by abeham, 14 years ago

#1330

  • fixed a small bug in a view
File size: 19.2 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Drawing;
24using System.Drawing.Drawing2D;
25using System.Drawing.Text;
26using System.Globalization;
27using System.Windows.Forms;
28using HeuristicLab.Analysis;
29using HeuristicLab.Common;
30using HeuristicLab.Data;
31using HeuristicLab.Encodings.PermutationEncoding;
32
33namespace HeuristicLab.Problems.QuadraticAssignment.Views {
34  public partial class QAPView : UserControl {
35    private Bitmap bitmap;
36    private Bitmap defaultBitmap;
37
38    #region Properties
39    private DoubleMatrix distances;
40    public DoubleMatrix Distances {
41      get { return distances; }
42      set {
43        DeregisterDistancesEvents();
44        distances = value;
45        RegisterDistancesEvents();
46        OnRedraw();
47      }
48    }
49
50    private DoubleMatrix weights;
51    public DoubleMatrix Weights {
52      get { return weights; }
53      set {
54        DeregisterWeightsEvents();
55        weights = value;
56        RegisterWeightsEvents();
57        OnRedraw();
58      }
59    }
60
61    private Permutation assignment;
62    public Permutation Assignment {
63      get { return assignment; }
64      set {
65        DeregisterAssignmentEvents();
66        assignment = value;
67        RegisterAssignmentEvents();
68        OnRedraw();
69      }
70    }
71    #endregion
72
73    #region Event Handling
74    private void DeregisterDistancesEvents() {
75      if (Distances != null) {
76        Distances.Reset -= new EventHandler(Redraw);
77        Distances.RowsChanged -= new EventHandler(Redraw);
78        Distances.ColumnsChanged -= new EventHandler(Redraw);
79        Distances.ItemChanged -= new EventHandler<EventArgs<int, int>>(Redraw);
80      }
81    }
82
83    private void RegisterDistancesEvents() {
84      if (Distances != null) {
85        Distances.Reset += new EventHandler(Redraw);
86        Distances.RowsChanged += new EventHandler(Redraw);
87        Distances.ColumnsChanged += new EventHandler(Redraw);
88        Distances.ItemChanged += new EventHandler<EventArgs<int, int>>(Redraw);
89      }
90    }
91
92    private void DeregisterWeightsEvents() {
93      if (Weights != null) {
94        Weights.Reset -= new EventHandler(Redraw);
95        Weights.RowsChanged -= new EventHandler(Redraw);
96        Weights.ColumnsChanged -= new EventHandler(Redraw);
97        Weights.ItemChanged -= new EventHandler<EventArgs<int, int>>(Redraw);
98      }
99    }
100
101    private void RegisterWeightsEvents() {
102      if (Weights != null) {
103        Weights.Reset += new EventHandler(Redraw);
104        Weights.RowsChanged += new EventHandler(Redraw);
105        Weights.ColumnsChanged += new EventHandler(Redraw);
106        Weights.ItemChanged += new EventHandler<EventArgs<int, int>>(Redraw);
107      }
108    }
109
110    private void DeregisterAssignmentEvents() {
111      if (Assignment != null) {
112        Assignment.Reset -= new EventHandler(Redraw);
113        Assignment.ItemChanged -= new EventHandler<EventArgs<int>>(Redraw);
114      }
115    }
116
117    private void RegisterAssignmentEvents() {
118      if (Assignment != null) {
119        Assignment.Reset += new EventHandler(Redraw);
120        Assignment.ItemChanged += new EventHandler<EventArgs<int>>(Redraw);
121      }
122    }
123
124    private void Redraw(object sender, EventArgs e) {
125      if (sender is RadioButton && !((RadioButton)sender).Checked)
126        return;
127      OnRedraw();
128    }
129
130    private void Redraw(object sender, EventArgs<int, int> e) {
131      OnRedraw();
132    }
133
134    private void pictureBox_SizeChanged(object sender, EventArgs e) {
135      SetupDefaultBitmap();
136      OnRedraw();
137    }
138    #endregion
139
140    public QAPView() {
141      InitializeComponent();
142      SetupDefaultBitmap();
143    }
144
145    private void SetupDefaultBitmap() {
146      if (defaultBitmap != null) {
147        defaultBitmap.Dispose();
148        defaultBitmap = null;
149      }
150      if (pictureBox.Width > 0 && pictureBox.Height > 0) {
151        defaultBitmap = new Bitmap(pictureBox.Width, pictureBox.Height);
152        WriteCenteredTextToBitmap(ref defaultBitmap, "No visualization available");
153      }
154    }
155
156    private void WriteCenteredTextToBitmap(ref Bitmap bitmap, string text) {
157      using (Graphics g = Graphics.FromImage(bitmap)) {
158        g.TextRenderingHint = TextRenderingHint.AntiAlias;
159        g.SmoothingMode = SmoothingMode.AntiAlias;
160
161        SizeF strSize = g.MeasureString(text, Font);
162        g.DrawString(text, Font, Brushes.Black, (float)(pictureBox.Width - strSize.Width) / 2.0f, (float)(pictureBox.Height - strSize.Height) / 2.0f);
163      }
164    }
165
166    private void OnRedraw() {
167      if (InvokeRequired) {
168        Invoke((Action)OnRedraw, null);
169      } else {
170        GenerateImage();
171      }
172    }
173
174    private void GenerateImage() {
175      if (pictureBox.Width > 0 && pictureBox.Height > 0) {
176        Bitmap newBitmap = null;
177        stressLabel.Text = "-";
178        if (distancesRadioButton.Checked && Distances != null && Distances.Rows > 0
179          && Distances.Rows == Distances.Columns) {
180          if (Distances.Rows > 30) {
181            newBitmap = new Bitmap(pictureBox.Width, pictureBox.Height);
182            WriteCenteredTextToBitmap(ref newBitmap, "Problem dimension too large for visualization.");
183          } else newBitmap = GenerateDistanceImage();
184        } else if (weightsRadioButton.Checked && Weights != null && Weights.Rows > 0
185          && Weights.Rows == Weights.Columns) {
186          if (Weights.Rows > 30) {
187            newBitmap = new Bitmap(pictureBox.Width, pictureBox.Height);
188            WriteCenteredTextToBitmap(ref newBitmap, "Problem dimension too large for visualization.");
189          } else newBitmap = GenerateWeightsImage();
190        } else if (assignmentRadioButton.Checked
191          && Assignment != null && Assignment.Length > 0
192          && Weights != null && Weights.Rows > 0
193          && Distances != null && Distances.Rows > 0
194          && Weights.Rows == Weights.Columns
195          && Distances.Rows == Distances.Columns
196          && Assignment.Length == Weights.Rows
197          && Assignment.Length == Distances.Rows
198          && Assignment.Validate()) {
199          if (Assignment.Length > 30) {
200            newBitmap = new Bitmap(pictureBox.Width, pictureBox.Height);
201            WriteCenteredTextToBitmap(ref newBitmap, "Problem dimension too large for visualization.");
202          } else newBitmap = GenerateAssignmentImage();
203        }
204
205        pictureBox.Image = newBitmap != null ? newBitmap : defaultBitmap;
206        if (bitmap != null) bitmap.Dispose();
207        if (newBitmap != null) bitmap = newBitmap;
208        else bitmap = null;
209      }
210    }
211
212    #region Draw distances
213    private Bitmap GenerateDistanceImage() {
214      if ((pictureBox.Width > 0) && (pictureBox.Height > 0)) {
215        Bitmap newBitmap = new Bitmap(pictureBox.Width, pictureBox.Height);
216
217        for (int i = 0; i < distances.Rows; i++) {
218          for (int j = i + 1; j < distances.Rows; j++)
219            if (distances[i, j] != distances[j, i]) {
220              WriteCenteredTextToBitmap(ref newBitmap, "Distance matrix is not symmetric");
221              return newBitmap;
222            }
223        }
224
225        double stress;
226        DoubleMatrix coordinates = MultidimensionalScaling.MetricByDistance(distances, out stress);
227        stressLabel.Text = stress.ToString("0.00", CultureInfo.CurrentCulture.NumberFormat);
228        double xMin = double.MaxValue, yMin = double.MaxValue, xMax = double.MinValue, yMax = double.MinValue;
229        double maxDistance = double.MinValue;
230        for (int i = 0; i < coordinates.Rows; i++) {
231          if (xMin > coordinates[i, 0]) xMin = coordinates[i, 0];
232          if (yMin > coordinates[i, 1]) yMin = coordinates[i, 1];
233          if (xMax < coordinates[i, 0]) xMax = coordinates[i, 0];
234          if (yMax < coordinates[i, 1]) yMax = coordinates[i, 1];
235
236          for (int j = i + 1; j < coordinates.Rows; j++) {
237            if (distances[i, j] > maxDistance) maxDistance = distances[i, j];
238            if (distances[j, i] > maxDistance) maxDistance = distances[j, i];
239          }
240        }
241
242        int border = 20;
243        double xStep = xMax != xMin ? (pictureBox.Width - 2 * border) / (xMax - xMin) : 1;
244        double yStep = yMax != yMin ? (pictureBox.Height - 2 * border) / (yMax - yMin) : 1;
245
246        Point[] points = new Point[coordinates.Rows];
247        for (int i = 0; i < coordinates.Rows; i++)
248          points[i] = new Point(border + ((int)((coordinates[i, 0] - xMin) * xStep)),
249                                newBitmap.Height - (border + ((int)((coordinates[i, 1] - yMin) * yStep))));
250
251        Random rand = new Random();
252        using (Graphics graphics = Graphics.FromImage(newBitmap)) {
253          graphics.SmoothingMode = SmoothingMode.AntiAlias;
254          graphics.TextRenderingHint = TextRenderingHint.AntiAlias;
255          graphics.DrawString("Showing locations spaced out according to their distances", Font, Brushes.Black, 5, 2);
256
257          for (int i = 0; i < coordinates.Rows - 1; i++) {
258            for (int j = i + 1; j < coordinates.Rows; j++) {
259              Point start = points[i], end = points[j];
260              string caption = String.Empty;
261              double d = Math.Max(distances[i, j], distances[j, i]);
262              float width = (float)Math.Ceiling(5.0 * d / maxDistance);
263              if (d > 0) {
264                graphics.DrawLine(new Pen(Color.IndianRed, width), start, end);
265                if (distances[i, j] != distances[j, i])
266                  caption = distances[i, j].ToString(CultureInfo.InvariantCulture.NumberFormat)
267                    + " / " + distances[j, i].ToString(CultureInfo.InvariantCulture.NumberFormat);
268                else
269                  caption = distances[i, j].ToString(CultureInfo.InvariantCulture.NumberFormat);
270              }
271              if (!String.IsNullOrEmpty(caption)) {
272                double r = rand.NextDouble();
273                while (r < 0.2 || r > 0.8) r = rand.NextDouble();
274                float x = (float)(start.X + (end.X - start.X) * r + 5);
275                float y = (float)(start.Y + (end.Y - start.Y) * r + 5);
276                graphics.DrawString(caption, Font, Brushes.Black, x, y);
277              }
278            }
279          }
280
281          for (int i = 0; i < points.Length; i++) {
282            Point p = new Point(points[i].X - 3, points[i].Y - 3);
283            graphics.FillRectangle(Brushes.Black, p.X, p.Y, 8, 8);
284            graphics.DrawString(i.ToString(), Font, Brushes.Black, p.X, p.Y + 10);
285          }
286        }
287        return newBitmap;
288      }
289      return null;
290    }
291    #endregion
292
293    #region Draw weights
294    private Bitmap GenerateWeightsImage() {
295      if ((pictureBox.Width > 0) && (pictureBox.Height > 0)) {
296        Bitmap newBitmap = new Bitmap(pictureBox.Width, pictureBox.Height);
297
298        double maxWeight = double.MinValue;
299        for (int i = 0; i < weights.Rows; i++)
300          for (int j = i + 1; j < weights.Rows; j++) {
301            if (weights[i, j] > maxWeight)
302              maxWeight = weights[i, j] + weights[j, i];
303
304            if (weights[i, j] != weights[j, i]) {
305              WriteCenteredTextToBitmap(ref newBitmap, "Weights matrix is not symmetric");
306              return newBitmap;
307            }
308          }
309
310        DoubleMatrix distances = new DoubleMatrix(weights.Rows, weights.Columns);
311        for (int i = 0; i < distances.Rows; i++)
312          for (int j = 0; j < distances.Columns; j++) {
313            distances[i, j] = maxWeight + 1 - weights[i, j];
314          }
315
316        double stress;
317        DoubleMatrix coordinates = MultidimensionalScaling.MetricByDistance(distances, out stress);
318        stressLabel.Text = stress.ToString("0.00", CultureInfo.CurrentCulture.NumberFormat);
319        double xMin = double.MaxValue, yMin = double.MaxValue, xMax = double.MinValue, yMax = double.MinValue;
320        for (int i = 0; i < coordinates.Rows; i++) {
321          if (xMin > coordinates[i, 0]) xMin = coordinates[i, 0];
322          if (yMin > coordinates[i, 1]) yMin = coordinates[i, 1];
323          if (xMax < coordinates[i, 0]) xMax = coordinates[i, 0];
324          if (yMax < coordinates[i, 1]) yMax = coordinates[i, 1];
325        }
326
327        int border = 20;
328        double xStep = xMax != xMin ? (pictureBox.Width - 2 * border) / (xMax - xMin) : 1;
329        double yStep = yMax != yMin ? (pictureBox.Height - 2 * border) / (yMax - yMin) : 1;
330
331        Point[] points = new Point[coordinates.Rows];
332        for (int i = 0; i < coordinates.Rows; i++)
333          points[i] = new Point(border + ((int)((coordinates[i, 0] - xMin) * xStep)),
334                                newBitmap.Height - (border + ((int)((coordinates[i, 1] - yMin) * yStep))));
335
336        Random rand = new Random();
337        using (Graphics graphics = Graphics.FromImage(newBitmap)) {
338          graphics.SmoothingMode = SmoothingMode.AntiAlias;
339          graphics.TextRenderingHint = TextRenderingHint.AntiAlias;
340          graphics.DrawString("Showing facilities spaced out according to their weights", Font, Brushes.Black, 5, 2);
341
342          for (int i = 0; i < coordinates.Rows - 1; i++) {
343            for (int j = i + 1; j < coordinates.Rows; j++) {
344              Point start = points[i], end = points[j];
345              string caption = String.Empty;
346              double d = Math.Max(distances[i, j], distances[j, i]);
347              double w = weights[i, j];
348              if (w > 0) {
349                float width = (float)Math.Ceiling(3.0 * w / maxWeight);
350                graphics.DrawLine(new Pen(Color.MediumBlue, width), start, end);
351                caption = w.ToString(CultureInfo.InvariantCulture.NumberFormat);
352              }
353              if (!String.IsNullOrEmpty(caption)) {
354                double r = rand.NextDouble();
355                while (r < 0.2 || r > 0.8) r = rand.NextDouble();
356                float x = (float)(start.X + (end.X - start.X) * r + 5);
357                float y = (float)(start.Y + (end.Y - start.Y) * r + 5);
358                graphics.DrawString(caption, Font, Brushes.Black, x, y);
359              }
360            }
361          }
362          for (int i = 0; i < points.Length; i++) {
363            Point p = new Point(points[i].X - 3, points[i].Y - 3);
364            graphics.FillRectangle(Brushes.Black, p.X, p.Y, 8, 8);
365            graphics.DrawString(i.ToString(), Font, Brushes.Black, p.X, p.Y + 10);
366          }
367        }
368        return newBitmap;
369      }
370      return null;
371    }
372    #endregion
373
374    #region Draw assignment
375    private Bitmap GenerateAssignmentImage() {
376      if ((pictureBox.Width > 0) && (pictureBox.Height > 0)) {
377        Bitmap newBitmap = new Bitmap(pictureBox.Width, pictureBox.Height);
378
379        for (int i = 0; i < distances.Rows; i++) {
380          for (int j = i + 1; j < distances.Rows; j++) {
381            if (distances[i, j] != distances[j, i]) {
382              WriteCenteredTextToBitmap(ref newBitmap, "Distance matrix is not symmetric");
383              return newBitmap;
384            }
385            if (weights[i, j] != weights[j, i]) {
386              WriteCenteredTextToBitmap(ref newBitmap, "Weights matrix is not symmetric");
387            }
388          }
389        }
390
391        double stress;
392        DoubleMatrix coordinates = MultidimensionalScaling.MetricByDistance(distances, out stress);
393        stressLabel.Text = stress.ToString("0.00", CultureInfo.CurrentCulture.NumberFormat);
394        double xMin = double.MaxValue, yMin = double.MaxValue, xMax = double.MinValue, yMax = double.MinValue;
395        double maxWeight = double.MinValue;
396        for (int i = 0; i < coordinates.Rows; i++) {
397          if (xMin > coordinates[i, 0]) xMin = coordinates[i, 0];
398          if (yMin > coordinates[i, 1]) yMin = coordinates[i, 1];
399          if (xMax < coordinates[i, 0]) xMax = coordinates[i, 0];
400          if (yMax < coordinates[i, 1]) yMax = coordinates[i, 1];
401
402          for (int j = i + 1; j < coordinates.Rows; j++) {
403            if (weights[i, j] > maxWeight) maxWeight = weights[i, j];
404          }
405        }
406
407        int border = 20;
408        double xStep = xMax != xMin ? (pictureBox.Width - 2 * border) / (xMax - xMin) : 1;
409        double yStep = yMax != yMin ? (pictureBox.Height - 2 * border) / (yMax - yMin) : 1;
410
411        Point[] points = new Point[coordinates.Rows];
412        for (int i = 0; i < coordinates.Rows; i++)
413          points[i] = new Point(border + ((int)((coordinates[i, 0] - xMin) * xStep)),
414                                newBitmap.Height - (border + ((int)((coordinates[i, 1] - yMin) * yStep))));
415
416        Random rand = new Random();
417        using (Graphics graphics = Graphics.FromImage(newBitmap)) {
418          graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
419          graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
420
421          for (int i = 0; i < assignment.Length - 1; i++) {
422            for (int j = i + 1; j < assignment.Length; j++) {
423              Point start, end;
424              string caption = String.Empty;
425              double d = distances[i, j];
426              start = points[assignment[i]];
427              end = points[assignment[j]];
428              double w = weights[i, j];
429              if (w > 0) {
430                float width = (float)Math.Ceiling(4.0 * w / maxWeight);
431                graphics.DrawLine(new Pen(Color.MediumBlue, width), start, end);
432                caption = w.ToString(CultureInfo.InvariantCulture.NumberFormat);
433              }
434              if (!String.IsNullOrEmpty(caption)) {
435                double r = rand.NextDouble();
436                while (r < 0.2 || r > 0.8) r = rand.NextDouble();
437                float x = (float)(start.X + (end.X - start.X) * r + 5);
438                float y = (float)(start.Y + (end.Y - start.Y) * r + 5);
439                graphics.DrawString(caption, Font, Brushes.Black, x, y);
440              }
441            }
442          }
443
444          for (int i = 0; i < points.Length; i++) {
445            Point p = new Point(points[i].X - 3, points[i].Y - 3);
446            graphics.FillRectangle(Brushes.Black, p.X, p.Y, 8, 8);
447            graphics.DrawString(i.ToString(), Font, Brushes.Black, p.X, p.Y + 10);
448          }
449        }
450        return newBitmap;
451      }
452      return null;
453    }
454    #endregion
455
456    private void CustomDispose(bool disposing) {
457      DeregisterDistancesEvents();
458      DeregisterWeightsEvents();
459      DeregisterAssignmentEvents();
460      if (bitmap != null) bitmap.Dispose();
461      bitmap = null;
462      if (defaultBitmap != null) {
463        defaultBitmap.Dispose();
464        defaultBitmap = null;
465      }
466    }
467  }
468}
Note: See TracBrowser for help on using the repository browser.