using System; using System.IO; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Threading; using System.Linq; using System.Text; using System.Windows.Forms; using TSP_Solver; using TSP; namespace TSPForm { public partial class TSPForm : Form { private static String aboutString = "Travelling Salesman Problem. Dr Mike Spann. Copyright 2011 \n\n" + "Greedy Algorithm - nearest neighbour search \n" + "ACO - ant colony optimization \n" + "ACO v2 - ACO with optimum path pheromone update and probabilistic decision rule \n" + "ACO v3 - ACO v2 with local search"; private readonly string initialImageDirectory; private SolidBrush brush = new SolidBrush(Color.Red); private Pen pen = new Pen(Color.Black); private double[,] TSPData; private int TSPGridsize; private int maxXCoord, minXCoord; private int maxYCoord, minYCoord; private double xDrawScale, yDrawScale; private int drawMarginSize = 5; private Boolean clearGraphics, plotRoute; private TSPGrid grid; private Thread TSPSolverThread; private TSPSolver solver; public TSPForm() { InitializeComponent(); currentRoutePanel.BackColor = Color.White; } public void optimumRouteChangeHandler() { currentTourLengthLabel.Text = "Current tour length: " + (int)solver.OptimumRouteLength; plotRoute = true; currentRoutePanel.Invalidate(); } public void progressReportHandler(double progress) { progressBar.Value = (int)progress; } public void statusReportHandler(string message) { localOptLabel.Text="Local Opt Improvement: " + message; } private void openFileDialog1_FileOk(object sender, CancelEventArgs e) { // Load the test data string fileName = openFileDialog1.FileName; if (fileName.Length != 0) { // Load TSP data in TSPLib format loadTSPData(fileName); } } private void resetGraphics() { // Clear existing graphics progressLabel.Text = null; progressBar.Value = 0; currentTourLengthLabel.Text = "Current tour length: "; localOptLabel.Text = "Local opt improvement: "; } private void loadTSPData(string fileName) { resetGraphics(); // Kill any threads if (TSPSolverThread!=null) if (TSPSolverThread.IsAlive) TSPSolverThread.Abort(); currentRoutePanel.Invalidate(); TSPGridsize = TSPLibReadFileHeader(fileName); TSPLibReadFile(fileName, TSPGridsize, ref TSPData); // Determine maximum and minimum x and y coordinates maxXCoord = Int32.MinValue; maxYCoord = Int32.MinValue; minXCoord = Int32.MaxValue; minYCoord = Int32.MaxValue; for (int i = 0; i < TSPGridsize; i++) { int x = (int)TSPData[i, 0]; int y = (int)TSPData[i, 1]; if (x > maxXCoord) maxXCoord = x; if (x < minXCoord) minXCoord = x; if (y > maxYCoord) maxYCoord = y; if (y < minYCoord) minYCoord = y; } // Set the scale factor for drawing the grid int width = currentRoutePanel.Size.Width; int height = currentRoutePanel.Size.Height; double xWidth = maxXCoord - minXCoord; double yWidth = maxYCoord - minYCoord; xDrawScale = (width - 3 * drawMarginSize) / xWidth; yDrawScale = (height - 3 * drawMarginSize) / yWidth; // Draw graphics clearGraphics = false; plotRoute = false; currentRoutePanel.Invalidate(); // Create TSP grid grid = new TSPGrid(TSPData, TSPGridsize); } private int TSPLibReadFileHeader(string fileName) { int count = -1; try { FileStream fromStream = new FileStream(fileName, FileMode.Open, FileAccess.Read); StreamReader fileReader = new StreamReader(fromStream); String input; do { input = fileReader.ReadLine(); if (input.StartsWith("NAME")) { dataSetLabel.Text = input; } else if (input.Contains("Optimum")) { int index = input.LastIndexOf(" is "); optimumTourLengthLabel.Text = "Optimum tour length: " + input.Substring(index + 3); } else if (input.StartsWith("DIMENSION")) { dimensionLabel.Text = input + " cities"; } } while (!input.Equals("NODE_COORD_SECTION")); do { input = fileReader.ReadLine(); count++; } while (!input.Equals("EOF")); } catch { MessageBox.Show("File access error. Filename " + fileName); } return count; } private void TSPLibReadFile(string fileName, int nData, ref double[,] data) { try { FileStream fromStream = new FileStream(fileName, FileMode.Open, FileAccess.Read); StreamReader fileReader = new StreamReader(fromStream); String input; do { input = fileReader.ReadLine(); } while (!input.Equals("NODE_COORD_SECTION")); data=new double[nData,2]; for (int i = 0; i < nData; i++) { input = fileReader.ReadLine(); string[] substrings = input.Split(' '); data[i,0] = Convert.ToDouble(substrings[1]); data[i,1] = Convert.ToDouble(substrings[2]); } } catch { MessageBox.Show("File access error. Filename " + fileName); } } private void currentRoutePanel_Paint(object sender, PaintEventArgs e) { Graphics graphics = e.Graphics; int width = currentRoutePanel.Size.Width; int height = currentRoutePanel.Size.Height; int[] xPanelCoord = new int[TSPGridsize]; int[] yPanelCoord = new int[TSPGridsize]; if (!clearGraphics) { for (int i = 0; i < TSPGridsize; i++) { int x = (int)TSPData[i, 0]; int y = (int)TSPData[i, 1]; x -= (int)minXCoord; y -= (int)minYCoord; x = (int)(drawMarginSize + x * xDrawScale); y = (int)(drawMarginSize + y * yDrawScale); xPanelCoord[i] = x; yPanelCoord[i] = y; graphics.FillEllipse(brush, x, y, 3, 3); } // Plot current estimate of the optimum route if (plotRoute) { lock (solver.OptimumRoute) { City cRight; int rightIndex; City cLeft = solver.OptimumRoute[0]; int leftIndex = cLeft.Index; for (int i = 1; i < TSPGridsize; i++) { cRight = solver.OptimumRoute[i]; rightIndex = cRight.Index; graphics.DrawLine(pen, xPanelCoord[leftIndex], yPanelCoord[leftIndex], xPanelCoord[rightIndex], yPanelCoord[rightIndex]); cLeft = cRight; leftIndex = cLeft.Index; } // Plot the final arc back to the start cRight = solver.OptimumRoute[0]; rightIndex = cRight.Index; graphics.DrawLine(pen, xPanelCoord[leftIndex], yPanelCoord[leftIndex], xPanelCoord[rightIndex], yPanelCoord[rightIndex]); } plotRoute = false; } } } private void TSPForm_FormClosed(object sender, FormClosedEventArgs e) { if (TSPSolverThread!=null) TSPSolverThread.Abort(); } private void currentRoutePanel_DoubleClick(object sender, EventArgs e) { currentTourLengthLabel.Text = "Current tour length: " + (int)solver.OptimumRouteLength; plotRoute = true; currentRoutePanel.Invalidate(); } private void selectTSPDatasetToolStripMenuItem_Click(object sender, EventArgs e) { // Open image file dialog box openFileDialog1.ShowDialog(); } private void exitToolStripMenuItem_Click_1(object sender, EventArgs e) { // Exit application if (TSPSolverThread != null) TSPSolverThread.Abort(); Application.Exit(); } private void greedyToolStripMenuItem_Click_1(object sender, EventArgs e) { resetGraphics(); solver = new TSPGreedySolver(grid); // Initialize the optimum route change event handler solver.OptimumRouteChangeEvent += new optimumRouteChangeDelegate(optimumRouteChangeHandler); // Initialize the progress report event handler solver.ProgressReportEvent += new progressReportDelegate(progressReportHandler); // Initialize solver thread if ((TSPSolverThread != null) && (TSPSolverThread.IsAlive)) TSPSolverThread.Abort(); TSPSolverThread = new Thread(new ThreadStart(solver.solve)); progressLabel.Text = "Greedy algorithm progress"; TSPSolverThread.Start(); } private void aCOToolStripMenuItem_Click_1(object sender, EventArgs e) { resetGraphics(); solver = new TSPACOSolver(grid); // Initialize the optimum route change event handler solver.OptimumRouteChangeEvent += new optimumRouteChangeDelegate(optimumRouteChangeHandler); // Initialize the progress report event handler solver.ProgressReportEvent += new progressReportDelegate(progressReportHandler); // Initialize solver thread if ((TSPSolverThread != null) && (TSPSolverThread.IsAlive)) TSPSolverThread.Abort(); TSPSolverThread = new Thread(new ThreadStart(solver.solve)); progressLabel.Text = "ACO algorithm progress"; TSPSolverThread.Start(); } private void aCOV2ToolStripMenuItem_Click(object sender, EventArgs e) { resetGraphics(); solver = new TSPACOSolverV2(grid); // Initialize the optimum route change event handler solver.OptimumRouteChangeEvent += new optimumRouteChangeDelegate(optimumRouteChangeHandler); // Initialize the progress report event handler solver.ProgressReportEvent += new progressReportDelegate(progressReportHandler); // Initialize the progress report event handler solver.StatusReportEvent += new statusReportDelegate(statusReportHandler); // Initialize solver thread if ((TSPSolverThread != null) && (TSPSolverThread.IsAlive)) TSPSolverThread.Abort(); TSPSolverThread = new Thread(new ThreadStart(solver.solve)); progressLabel.Text = "ACO v.2 algorithm progress"; TSPSolverThread.Start(); } private void aCOV3ToolStripMenuItem_Click(object sender, EventArgs e) { resetGraphics(); solver = new TSPACOSolverV3(grid); // Initialize the optimum route change event handler solver.OptimumRouteChangeEvent += new optimumRouteChangeDelegate(optimumRouteChangeHandler); // Initialize the progress report event handler solver.ProgressReportEvent += new progressReportDelegate(progressReportHandler); // Initialize the progress report event handler solver.StatusReportEvent += new statusReportDelegate(statusReportHandler); // Initialize solver thread if ((TSPSolverThread != null) && (TSPSolverThread.IsAlive)) TSPSolverThread.Abort(); TSPSolverThread = new Thread(new ThreadStart(solver.solve)); progressLabel.Text = "ACO v.3 algorithm progress"; TSPSolverThread.Start(); } private void aboutToolStripMenuItem_Click(object sender, EventArgs e) { MessageBox.Show(aboutString); } } }