private void drawTour(CTour tour, float depth, float red, float green, float blue, bool specialColor = false) { if (tour == null) { return; } Gl.glLineWidth(3f); Gl.glColor3f(red, green, blue); Gl.glBegin(Gl.GL_LINE_STRIP); for (int pointIndex = 0; pointIndex < tour.getListLength(); pointIndex++) { if (specialColor == true) { float color = (float)pointIndex / (float)tour.getListLength(); Gl.glColor3f(color, color, 0.5f); } CTSPPoint point = tour.getPoint(pointIndex); Gl.glVertex3f(point.x, point.y, depth); } Gl.glEnd(); }
private string handleNodeCoordSection(StreamReader reader) { String actualLine = reader.ReadLine(); int i = 1; if (mFileHeader.dimension == 0) { mFileHeader.dimension = Int32.MaxValue; } while ((!(actualLine == "EOF")) && (i <= mFileHeader.dimension)) { CTSPPoint point = parseLineToPoint(actualLine); CTSPPointList.getInstance().addPoint(point); actualLine = reader.ReadLine(); i++; } // Nachdem alle Punkte eingefügt wurden noch die Liste optimieren, // da sich hier eigentlich nichts mehr ändern sollte CTSPPointList.getInstance().optimizeList(); // Nachdem wir alle Punkte ausgelesen haben, können wir nun die Verbindungen nach // im FileHeader angegebenen Algorithmus berechnen CConnectionList.getInstance().generateFromPointList(mFileHeader.edgeWeightType); PerformanceCounter freeMemory = new PerformanceCounter("Memory", "Available Bytes"); Debug.WriteLine("Am Ende RAM frei: " + freeMemory.RawValue); Debug.WriteLine("Endspeicher: " + GC.GetTotalMemory(true)); return(actualLine); }
// Entspricht in der Formel: // Sum l( (t il) ^ alpha * (n il) ^ beta ) private double calculateSumFactorOfPossibleConnections(CTSPPoint currentPoint, CTSPPoint startPoint, CTSPPointList listOfPointsToTravel) { double sumFactorOfPossibleConnections = 0; foreach (CTSPPoint possiblePoint in listOfPointsToTravel) { CConnection connection = mConnectionList.getConnection(currentPoint, possiblePoint); double n_il = calculateLocalInformation(connection); double t_il = calculatePheromoneTrail(connection); sumFactorOfPossibleConnections += n_il * t_il; } // wir müssen natürlich auch den Weg zurück zum Startpunkt beachten, der darf aber nicht in der // Liste der noch zu besuchenden Punkte stehen. // Daher müssen wir diesen nochmal explizit am ende einbeziehen CConnection startConnection = mConnectionList.getConnection(startPoint, currentPoint); if (startConnection != null) { double start_n_il = calculateLocalInformation(startConnection); double start_t_il = calculatePheromoneTrail(startConnection); sumFactorOfPossibleConnections += start_n_il * start_t_il; } return(sumFactorOfPossibleConnections); }
private static void generatePoints() { Random rand = new Random(); for (int cityIndex = 0; cityIndex < mNumPoints; cityIndex++) { CTSPPoint createdPoint = new CTSPPoint(rand.Next(1000), rand.Next(1000), ""); CTSPPointList.getInstance().addPoint(createdPoint); } }
private string handleTourSection(StreamReader reader) { String actualLine = reader.ReadLine(); if (mFileHeader.dimension == 0) { mFileHeader.dimension = Int32.MaxValue; } // Die Anzahl der Knoten in der Datei muss mit der Anzahl der Einträge in der Punktliste übereinstimmen. // Sonst greifen wir eventuell noch auf Punkte zu die es nicht gibt. if (mFileHeader.dimension != CTSPPointList.getInstance().length()) { throw new Exception("Tour-Datei ist nicht kompatibel mit der geladenen TSP-Datei!"); } CTour optTour = new CTour(); int i = 1; while ((!(actualLine == "-1")) && (i <= mFileHeader.dimension)) { actualLine = actualLine.Trim(); // Punkt suchen CTSPPoint point = CTSPPointList.getInstance().getPoint(actualLine); if (point != null) { // Punkt in Tour einfügen optTour.addPoint(point); } else { throw new Exception("Fehler beim auslesen der Optimalen Tour!"); } actualLine = reader.ReadLine(); i++; } // prüfen ob die Tour ein Kreis ist (erstes == letztes Element) if (optTour.getPoint(0) != optTour.getPoint(optTour.getListLength() - 1)) { // Nein, also den Kreis herstellen optTour.addPoint(optTour.getPoint(0)); } // Tour abspeichern CAntAlgorithmParameters.getInstance().optTour = optTour; return(actualLine); }
public void CreateNewAnts() { Random random = new Random(); int numPoints = CTSPPointList.getInstance().length(); for (int i = 0; i < arrayOfAnts.Length; i++) { int randomPointIndex = random.Next(numPoints); CTSPPoint randomPoint = CTSPPointList.getInstance().getPoint(randomPointIndex); arrayOfAnts[i] = new CAnt(randomPoint); } }
private void drawAllConnections() { CConnectionList connList = CConnectionList.getInstance(); // zuerst bestimmen wie hoch der höchste Pheromonwert aller Verbindungen ist // damit wir beim zeichnen der Verbindungen diese Abhängig von ihrem Wert, dunkler // oder heller zeichnen können float highestPhermone = 0; foreach (CConnection connection in connList) { if (connection.getPheromone() > highestPhermone) { highestPhermone = connection.getPheromone(); } } Gl.glLineWidth(1f); // Verbindungen Zeichnen foreach (CConnection connection in connList) { // Farbe abhängig vom Pheromonwert der Verbindung setzen // => hohe Werte werden dunkel dagestellt // => niedrige hell float pheromonLevel = 1; if (highestPhermone != 0f) { pheromonLevel = connection.getPheromone() / highestPhermone; } // Die Verbindungen die einen geringen Pheromonwert haben sollen nicht angezeigt werden //if (pheromonLevel > 0.1) { // 0.0 == schwarz // 1.0 == weiß float color = 1 - pheromonLevel; Gl.glColor3f(color, color, color); // Eckpunkte bestimmen CTSPPoint sourcePoint = null; CTSPPoint destinationPoint = null; connection.getPoints(out sourcePoint, out destinationPoint); float depth = CONNECTION_DRAW_LAYER - (color * 100f); // Linien Zeichnen Gl.glBegin(Gl.GL_LINES); Gl.glVertex3d(sourcePoint.x, sourcePoint.y, depth); Gl.glVertex3d(destinationPoint.x, destinationPoint.y, depth); Gl.glEnd(); } } }
/// <summary> /// Prüft ob ein Punkt in der Verbindung enthalten ist /// </summary> /// <param name="tspPoint">Punkt der in der Verbindung enthalten sein soll</param> /// <returns>true - Punkt ist in der Verbindung enthalten; false - Punkt ist NICHT teil der Verbindung</returns> public bool containsPoint(CTSPPoint tspPoint) { if (mTSPPoint1 == tspPoint) { return(true); } if (mTSPPoint2 == tspPoint) { return(true); } return(false); }
public void addPoint(CTSPPoint point) { if (mPoints.length() == 0) { mTourLength = 0; } else { CTSPPoint lastPointInList = mPoints.getPoint(mPoints.length() - 1); CConnection additinalConnection = CConnectionList.getInstance().getConnection(lastPointInList, point); mTourLength += additinalConnection.getDistance(); } mPoints.addPoint(point); }
/// <summary> /// fügt einen Punkt in die Liste ein /// </summary> /// <param name="point">Punkt der eingefügt werden soll</param> public void addPoint(CTSPPoint point) { // normal wird die Kapazität immer verdoppelt wenn ein Element // zusätzlich eingefügt wird. Das kann aber einen enormen Overhead // zur folge haben. Darum erhöhen wir Manuell um kleine Schritte if (mPointList.Count + 1 >= mPointList.Capacity) { if (mPointList.Capacity > 128) { mPointList.Capacity += 128; } } mPointList.Add(point); }
private void drawPoints() { Gl.glPointSize(5); Gl.glColor3f(1.0f, 0f, 0f); // Städte Zeichnen CTSPPointList pointList = CTSPPointList.getInstance(); for (int pointIndex = 0; pointIndex < pointList.length(); pointIndex++) { CTSPPoint point = pointList.getPoint(pointIndex); Gl.glBegin(Gl.GL_POINTS); Gl.glVertex3d(point.x, point.y, POINT_DRAW_LAYER); Gl.glEnd(); } }
public void handleAnt(object antObject) { CAnt ant = (CAnt)antObject; // Ameisen laufen lassen for (var i = 0; i < CTSPPointList.getInstance().length(); i++) { CTSPPoint nextPoint = decisionNextPoint(ant.CurrentPoint, ant.GetTour().getPoint(0), ant.PointsToVisit); if (nextPoint == null) { nextPoint = ant.GetTour().getPoint(0); } ant.CurrentPoint = nextPoint; } }
protected T_BOUNDS getBounds(CTSPPointList citys) { T_BOUNDS ret = new T_BOUNDS(); if (citys.length() > 0) { ret.left = double.MaxValue; ret.bottom = double.MaxValue; for (int cityIndex = 0; cityIndex < citys.length(); cityIndex++) { CTSPPoint city = citys.getPoint(cityIndex); if (city.x < ret.left) { ret.left = city.x; } if (city.y < ret.bottom) { ret.bottom = city.y; } if (city.x > ret.right) { ret.right = city.x; } if (city.y > ret.top) { ret.top = city.y; } } } else { ret.left = 0; ret.bottom = 0; ret.right = this.Width; ret.top = this.Height; } return(ret); }
/// <summary> /// holt eine Verbindung aus der Liste und gibt diese zurück /// </summary> /// <param name="tspPoint1">Punkt 1 der in der Verbindung vorhanden sein muss</param> /// <param name="tspPoint2">Punkt 2 der in der Verbindung vorhanden sein muss</param> /// <returns>gefundene Verbindung oder null</returns> public CConnection getConnection(CTSPPoint tspPoint1, CTSPPoint tspPoint2) { if ((mConnectionList == null) || (mConnectionsAdded == 0)) { return(null); } // alle Verbindungen durchgehen foreach (CConnection connection in mConnectionList) { // wenn die Verbindung beide Punkte enthält ist das die gesuchte Verbindung if (connection.containsPoint(tspPoint1, tspPoint2) == true) { return(connection); } } return(null); }
public bool containsPoint(CTSPPoint tspPoint1, CTSPPoint tspPoint2) { if (mTSPPoint1 == tspPoint1) { if (mTSPPoint2 == tspPoint2) { return(true); } } else if (mTSPPoint1 == tspPoint2) { if (mTSPPoint2 == tspPoint1) { return(true); } } return(false); }
private void handleCursorAction(CVector2f position) { if (mCursorAction.add) { try { CMemoryTester.fitMemory(CTSPPointList.getInstance().length() + 1); } catch (CInsufficientMemoryException memoryException) { if (memoryException.getType() == CInsufficientMemoryException.E_EXCEPTION_TYPE.E_32_BIT_ERROR) { MessageBox.Show("Um ein Projekt mit einem Knoten mehr erzeugen zu können, benötigen Sie ca. " + memoryException.getMemoryNeeded() + " MByte. 32-Bit-Anwendungen können aber maximal " + memoryException.getMemoryAvailable() + " MByte verwalten. " + "Bitte verwenden sie die 64-Bit Version oder verwenden Sie ein geringe Anzahl an Punkten.", "Fehler!", MessageBoxButtons.OK, MessageBoxIcon.Error); } else { MessageBox.Show("Auf ihrem System stehen noch " + memoryException.getMemoryAvailable() + " MByte zur Verfügung. Es werden aber ca. " + memoryException.getMemoryNeeded() + " MByte benötigt. " + "Wenn Sie ein Projekt mit einer höheren Anzahl von Punkten verwenden möchten stellen Sie Bitte mehr RAM zur Verfügung.", "Fehler!", MessageBoxButtons.OK, MessageBoxIcon.Error); } } CTSPPointList.getInstance().addPoint(new CTSPPoint(position.x, position.y)); } if (mCursorAction.del) { float precision = (float)((mBounds.right - mBounds.left) / 100); CTSPPoint Point = CTSPPointList.getInstance().getPointsbyCoordinates(position.x, position.y, precision); if (!(Point == null)) { CTSPPointList.getInstance().remove(Point); } } if (mCursorAction.change) { pointToMove.movePoint = false; } }
/// <summary> /// Konstruktor /// </summary> /// <param name="tspPoint1">Punkt 1 der Verbindung</param> /// <param name="tspPoint2">Punkt 2 der Verbindung</param> /// <param name="distanceCalculation">Gibt an auf welche Art die Entfernung zwischen den Punkten berechnet werden soll</param> /// <param name="initialPheromone">Pheromon das die Verbindung von Beginn an haben soll</param> public CConnection(CTSPPoint tspPoint1, CTSPPoint tspPoint2, CTSPLibFileParser.E_EDGE_WEIGHT_TYPE distanceCalculation, float initialPheromone = 0) { mTSPPoint1 = tspPoint1; mTSPPoint2 = tspPoint2; mDistanceCalculation = distanceCalculation; if (initialPheromone <= 0) { mPheromone = MIN_PHEROMONE; } else { mPheromone = initialPheromone; } calculateDistance(); // es wurde eine Verbindung erzeugt .. also ein Schritt erfolgreich abgearbeteitet CProgressManager.stepDone(); }
public void mMouseDown(object sender, EventArgs args) { if (mCursorAction.change) { System.Windows.Forms.MouseEventArgs mouseArgs = (System.Windows.Forms.MouseEventArgs)args; if (mouseArgs.Button == System.Windows.Forms.MouseButtons.Left) { CVector2f position = getPositionFromMouseClick(mouseArgs); float precision = (float)((mBounds.right - mBounds.left) / 100); CTSPPoint Point = CTSPPointList.getInstance().getPointsbyCoordinates(position.x, position.y, precision); if (!(Point == null)) { pointToMove.movePoint = true; pointToMove.pointToMove = Point; } } } }
/// <summary> /// ermittelt alle Verbindungen in denen ein Punkt enthalten ist /// und gibt die Liste zurück /// </summary> /// <param name="tspPoint">Punkt dessen Verbindungen gesucht werden sollen</param> /// <returns>Liste mit Verbindungen des Punktes</returns> public List <CConnection> getConnectionOfPoint(CTSPPoint tspPoint) { List <CConnection> ret = new List <CConnection>(); if (mConnectionList != null) { // alle Verbindungen durchgehen foreach (CConnection connection in mConnectionList) { // wenn die Verbindung den gesuchten Punkt enthält, diesen in die Liste aufnehmen if (connection.containsPoint(tspPoint) == true) { ret.Add(connection); } } } // die Liste der Verbindungen für den Punkt zurückgeben return(ret); }
private string handleDisplayDataSection(StreamReader reader) { if (mFileHeader.displayDataType != E_DISPLAY_DATA_TYPE.E_TWOD_DISPLAY) { throw new Exception("Fehler beim lesen der Anzeigedaten!"); } // da es sein kann das die DisplayDataSection nach der EdgeWeightSection kommt und // die Punkte damit schon angelegt sind müssen zuerst ermittelt werden, ob neue Punkte // angelegt werden müssen oder die bestehenden verwendet werden können bool bCreateNewPoints = CTSPPointList.getInstance().length() == 0; int nodeIndex = 0; string actualLine = reader.ReadLine(); while ((actualLine != null) && (actualLine != "EOF") && (nodeIndex <= mFileHeader.dimension)) { CTSPPoint point = parseLineToPoint(actualLine); if (bCreateNewPoints == true) { CTSPPointList.getInstance().addPoint(point); } else { CTSPPoint storedPoint = CTSPPointList.getInstance().getPoint(nodeIndex); storedPoint.setLabel(point.getLabel()); storedPoint.x = point.x; storedPoint.y = point.y; } nodeIndex++; actualLine = reader.ReadLine(); } // Nachdem alle Punkte eingefügt wurden noch die Liste optimieren, // da sich hier eigentlich nichts mehr ändern sollte CTSPPointList.getInstance().optimizeList(); return(actualLine); }
public CTSPPoint decisionNextPoint(CTSPPoint currentPoint, CTSPPoint startPoint, CTSPPointList listOfPointsToTravel) { // Formel: // (t ij) ^ alpha * (n ij) ^ beta // p ij = ---------------------------------- // Sum l( (t il) ^ alpha * (n il) ^ beta ) // // i = Startpunkt // j = Zielpunkt // l = ein Punkt von den noch zu Besuchenden Punkten // zuerst berechnen wir mal den Divisor der Formel, da dieser einmal pro Bewegung berechnet werden muss double sumFactorOfPossibleConnections = calculateSumFactorOfPossibleConnections(currentPoint, startPoint, listOfPointsToTravel); // jetzt berechnen wir die probability p von allen Verbindungen und bestimmen die beste double bestProbability = 0; CTSPPoint bestTarget = null; foreach (CTSPPoint possibleTarget in listOfPointsToTravel) { CConnection connection = mConnectionList.getConnection(currentPoint, possibleTarget); // von diesem Punkt erstmal die Werte für (t ij) ^ alpha und (n ij) ^ beta berechnen. // Damit haben wir dann die Werte für den Dividenten double t_ij = calculatePheromoneTrail(connection); double n_ij = calculateLocalInformation(connection); // die probability berechnen double probability = (t_ij * n_ij) / sumFactorOfPossibleConnections; // die der probability-Wert höher besser? if (probability > bestProbability) { // dann merken wir uns diesen Punkt bestProbability = probability; bestTarget = possibleTarget; } } return(bestTarget); }
/// <summary> /// Löscht einen bestimmten Punkt aus der Liste /// </summary> /// <param name="point"></param> public bool remove(CTSPPoint point) { return(mPointList.Remove(point)); }
public void getPoints(out CTSPPoint tspPoint1, out CTSPPoint tspPoint2) { tspPoint1 = mTSPPoint1; tspPoint2 = mTSPPoint2; }
private void handleEdgeWeightElement(string element, int elementIndex) { CTSPPointList pointList = CTSPPointList.getInstance(); CConnectionList connList = CConnectionList.getInstance(); float distance = float.Parse(element); switch (mFileHeader.edgeWeightFormat) { case E_EDGE_WEIGHT_FORMAT.E_FULL_MATRIX: { int row = elementIndex / mFileHeader.dimension; int pointIndex = elementIndex % mFileHeader.dimension; // Es werden nur die Punkte unter der Diagonalen betrachtet. // damit werden keine Verbindungen Doppelt eingefügt und Verbindungen // auf den gleichen Punkt, also Distanz = 0, vermieden if (pointIndex < row) { CTSPPoint point1 = pointList.getPoint(row); CTSPPoint point2 = pointList.getPoint(pointIndex); connList.addConnection(new CConnection(point1, point2, distance, CAntAlgorithmParameters.getInstance().initialPheromone)); } break; } case E_EDGE_WEIGHT_FORMAT.E_UPPER_ROW: { int row = 0; while ((elementIndex / (mFileHeader.dimension - 1 - row)) > 0) { elementIndex -= (mFileHeader.dimension - 1 - row); row++; } // Index des Punktes ist der Offset bis zur Diagonalen + den Index des Elementes int pointIndex = row + 1 + elementIndex; CTSPPoint point1 = pointList.getPoint(row); CTSPPoint point2 = pointList.getPoint(pointIndex); connList.addConnection(new CConnection(point1, point2, distance, CAntAlgorithmParameters.getInstance().initialPheromone)); break; } case E_EDGE_WEIGHT_FORMAT.E_UPPER_DIAG_ROW: { int row = 0; while ((elementIndex / (mFileHeader.dimension - row)) > 0) { elementIndex -= (mFileHeader.dimension - row); row++; } // Index des Punktes ist der Offset bis zur Diagonalen + den Index des Elementes int pointIndex = row + elementIndex; if (pointIndex != row) { CTSPPoint point1 = pointList.getPoint(row); CTSPPoint point2 = pointList.getPoint(pointIndex); connList.addConnection(new CConnection(point1, point2, distance, CAntAlgorithmParameters.getInstance().initialPheromone)); } break; } case E_EDGE_WEIGHT_FORMAT.E_LOWER_DIAG_ROW: { int row = 0; int pointIndex = elementIndex; while ((pointIndex / (row + 1)) > 0) { pointIndex -= row + 1; row++; } if (pointIndex != row) { CTSPPoint point1 = pointList.getPoint(pointIndex); CTSPPoint point2 = pointList.getPoint(row); connList.addConnection(new CConnection(point1, point2, distance, CAntAlgorithmParameters.getInstance().initialPheromone)); } break; } } }
public CAnt(CTSPPoint startPoint) { tour = new CTour(); PointsToVisit = CTSPPointList.getInstance().copy(); CurrentPoint = startPoint; }
public void startAlgorithm() { CProgressManager.setStepsIteration(mMaxIterations); mConnectionList.SetInitialPheromone(mInitialPheromone); mItertationsTextbox.Invoke(new Action(delegate() { mItertationsTextbox.Text = "0/" + mMaxIterations; })); DateTime startTime = DateTime.Now; int iteration = 0; bool bStopAlgorithm = false; while ((iteration < mMaxIterations) && (bStopAlgorithm == false)) { NewIteration(); // Evaporation (verdunstung) //-------------------------------- // Dazu iterieren wir durch alle Verbindungen und lassen das Pheromon verdunsten foreach (CConnection connection in mConnectionList) { connection.evaporate(mEvaporationFactor); } // Pheromon-Update //-------------------------------- // Dazu durch alle Touren von allen Ameisen nachgehen und für jede Verbindung die // Pheromonwerte neu berechnen // Formel: delta(t ij) = Q / (distance ij) foreach (CAnt ant in arrayOfAnts) { CTour antTour = ant.GetTour(); // wir fangen mit Index 1 an! Damit die Punkte der Verbindungen mit den Indizies // index -1 und index geholt werden können for (int pointIndex = 1; pointIndex < antTour.getListLength(); pointIndex++) { CTSPPoint fromPoint = antTour.getPoint(pointIndex - 1); CTSPPoint toPoint = antTour.getPoint(pointIndex); CConnection tourConnection = mConnectionList.getConnection(fromPoint, toPoint); tourConnection.addPheromone(mPhermomoneUpdate); } } CIterationList.getInstance().refreshStatisticNumbers(); mRenderWindow.Invoke(mRenderWindow.refreshDelegate); CProgressManager.stepDone(); mItertationsTextbox.Invoke(new Action(delegate() { mItertationsTextbox.Text = (iteration + 1) + "/" + mMaxIterations; })); Debug.WriteLine("Iteration done: " + (iteration + 1)); // Stopkriterien testen bStopAlgorithm = checkStopCriteria(); // Iterationszähler erhöhen iteration++; } Debug.WriteLine("Dauer: " + (DateTime.Now - startTime).TotalSeconds + " sek"); }