private void CreateSolution(IEnumerable<TsPoint> points, TspSolution solution, TsPoint firstPoint) { var notVisited = new List<TsPoint>(points.Where(p => p.Id != firstPoint.Id)); var last = firstPoint; while (notVisited.Any()) { var next = GetClosestPoint(last, notVisited); //check for potential orphans var pointsAbove = notVisited.Where(p => p != next && p.Y > last.Y).ToArray(); var pointsBelow = notVisited.Where(p => p != next && p.Y < last.Y).ToArray(); var pointsRight = notVisited.Where(p => p != next && p.X > last.X).ToArray(); var pointsLeft = notVisited.Where(p => p != next && p.X < last.X).ToArray(); TsPoint theAbove = null; TsPoint theBelow = null; TsPoint theRight = null; TsPoint theLeft = null; if (pointsAbove.Length == 1) { theAbove = pointsAbove.Single(); if (next.DistanceFrom(last) / theAbove.DistanceFrom(last) < _threshold) theAbove = null; } if (pointsBelow.Length == 1) { theBelow = pointsBelow.Single(); if (next.DistanceFrom(last) / theBelow.DistanceFrom(last) < _threshold) theBelow = null; } if (pointsRight.Length == 1) { theRight = pointsRight.Single(); if (next.DistanceFrom(last) / theRight.DistanceFrom(last) < _threshold) theRight = null; } if (pointsLeft.Length == 1) { theLeft = pointsLeft.Single(); if (next.DistanceFrom(last) / theLeft.DistanceFrom(last) < _threshold) theLeft = null; } var nextPoints = new[] { theAbove, theBelow, theRight, theLeft }.Where(p => p != null).ToList(); if (nextPoints.Any()) { var unOrphaned = GetClosestPoint(last, nextPoints); notVisited.Remove(unOrphaned); last = unOrphaned; solution.AddNext(unOrphaned); } else { notVisited.Remove(next); last = next; solution.AddNext(next); } } }
public TspSolution Execute(TsPoint[] points) { var sortedPoints = points.OrderBy(p => p.X).ThenBy(p => p.Y); var firstPoint = sortedPoints.First(); var solution = new TspSolution(firstPoint); foreach (var point in sortedPoints.Skip(1)) solution.AddNext(point); solution.Close(); return solution; }
public TspSolution Execute(TsPoint[] points) { TspSolution current = null; var sortedPoints = points.OrderBy(p => p.X + p.Y).ToArray(); for (double ts = .5; ts < 1.00; ts = ts + .01) { var newSolution = new TspSolver01(ts).Execute(sortedPoints); if (current == null || newSolution.Distance < current.Distance) current = newSolution; } if (current != null) current.OutputToDebug(); return current; }
public TspSolution Execute(TsPoint[] points) { var minX = points.Min(p => p.X); var maxX = points.Max(p => p.X); var rangeMinX = 1.1*minX; var rangeMaxX = .9*maxX; TsPoint upperRight = null; TsPoint upperLeft = null; TsPoint lowerRight = null; TsPoint lowerLeft = null; foreach (var point in points.Skip(1)) { if (point.X >= rangeMaxX) { if (upperRight == null || point.Y >= upperRight.Y) upperRight = point; if (lowerRight == null || point.Y <= lowerRight.Y) lowerRight = point; } else if(point.X <= rangeMinX) { if (upperLeft == null || point.Y >= upperLeft.Y) upperLeft = point; if (lowerLeft == null || point.Y <= lowerLeft.Y) lowerLeft = point; } } var solution1 = CreateSolution(points.Where(p => p != upperRight).ToArray(), upperRight); solution1.OutputToDebug(); var solution2 = CreateSolution(points.Where(p => p != upperRight).ToArray(), lowerRight); solution2.OutputToDebug(); if (solution2.Distance < solution1.Distance) solution1 = solution2; var solution3 = CreateSolution(points.Where(p => p != upperRight).ToArray(), upperLeft); solution3.OutputToDebug(); if (solution3.Distance < solution1.Distance) solution1 = solution3; var solution4 = CreateSolution(points.Where(p => p != upperRight).ToArray(), lowerLeft); solution4.OutputToDebug(); if (solution4.Distance < solution1.Distance) solution1 = solution4; return solution1; }
private TspSolution CreateSolution(TsPoint[] points, TsPoint firstPoint) { var solution = new TspSolution(firstPoint); var alreadyVisited = new List<int> { firstPoint.Id }; var last = firstPoint; while (alreadyVisited.Count != points.Length) { var notVisited = points.Where(p => !alreadyVisited.Contains(p.Id)).ToArray(); var next = notVisited.Aggregate(notVisited.First(), (min, curr) => curr.DistanceFrom(last) < min.DistanceFrom(last) ? curr : min); alreadyVisited.Add(next.Id); last = next; solution.AddNext(next); } solution.Close(); return solution; }
public TspSolution Execute(TsPoint[] points) { var minX = points.Min(p => p.X); var maxX = points.Max(p => p.X); var increment = (maxX - minX) / _steps; TspSolution solution = null; for (int i = 1; i <= _steps; i++) { var range = minX + increment; if (i == _steps) ++range; var thesePoints = points.Where(p => p.X >= minX && p.X < range).ToList(); TsPoint firstPoint; if (solution == null) { firstPoint = thesePoints.OrderBy(p => p.Y).First(); solution = new TspSolution(firstPoint); } else { firstPoint = GetClosestPoint(solution.LastItem, thesePoints); solution.AddNext(firstPoint); } CreateSolution(thesePoints, solution, firstPoint); minX = range; } if (solution != null) { solution.Close(); solution.OutputToDebug(); } return solution; }
public TspSolution Execute(TsPoint[] points) { var minX = points.Min(p => p.X); var maxX = points.Max(p => p.X); var minY = points.Min(p => p.Y); var maxY = points.Max(p => p.Y); const int pageSize = 7; var stepX = (maxX - minX) / pageSize; var stepY = (maxY - minY) / pageSize; var groups = new List<TspGroup>(); var goingDown = false; var sortNumber = 0; for (var x = minX; x < maxX; x = x + stepX) { if (goingDown) sortNumber += pageSize-1; else if (sortNumber > 0) sortNumber += pageSize+1; for (var y = minY; y < maxY; y = y + stepY) { var sort = goingDown ? sortNumber-- : sortNumber++; //Console.WriteLine(sort); var group = new TspGroup {SortNumber = sort, MinX = x, MaxX = x+stepX, MinY = y, MaxY = y+stepY}; groups.Add(group); if ((y + stepY) > (maxY - (stepY / pageSize))) { group.MaxY = maxY + 1; y = maxY; } if ((x + stepX) > (maxX - (stepX / pageSize))) { group.MaxX = maxX + 1; } } if ((x + stepX) > (maxX - (stepX / pageSize))) { x = maxX; } goingDown = !goingDown; } var sortedGroups = groups.OrderBy(g => g.SortNumber).ToArray(); for (var i = 0; i < sortedGroups.Length; i++) { var group = sortedGroups[i]; bool goingUp = ((group.SortNumber / pageSize) % 2) == 0; TsPoint[] pointsPage; var pointsPage1 = points.Where(p => p.X >= group.MinX && p.X < group.MaxX && p.Y >= group.MinY && p.Y < group.MaxY); if (goingUp) pointsPage = pointsPage1.OrderBy(p => p.X).ThenBy(p => p.Y).ToArray(); else pointsPage = pointsPage1.OrderBy(p => p.X).ThenByDescending(p => p.Y).ToArray(); var firstPoint = pointsPage.First(); if (_solution == null) { _solution = new TspSolution(firstPoint); } else { var lastItem = _solution.LastItem; firstPoint = pointsPage.Aggregate(firstPoint, (min, curr) => curr.DistanceFrom(lastItem) < min.DistanceFrom(lastItem) ? curr : min); _solution.AddNext(firstPoint); } var alreadyVisited = new List<int> { firstPoint.Id }; var last = firstPoint; while (alreadyVisited.Count != pointsPage.Length) { var notVisited = pointsPage.Where(p => !alreadyVisited.Contains(p.Id)).ToArray(); var next = notVisited.Aggregate(notVisited.First(), (min, curr) => curr.DistanceFrom(last) < min.DistanceFrom(last) ? curr : min); alreadyVisited.Add(next.Id); last = next; _solution.AddNext(next); } } _solution.Close(); return _solution; }
private TsPoint GetClosestPoint(TsPoint referencePoint, List<TsPoint> points) { var result = points.Aggregate(points.First(), (min, curr) => curr.DistanceFrom(referencePoint) < min.DistanceFrom(referencePoint) ? curr : min); return result; }
private void CreateSolutionOld(TsPoint[] points, TspSolution solution, TsPoint firstPoint) { var alreadyVisited = new List<int> { firstPoint.Id }; var last = firstPoint; while (alreadyVisited.Count != points.Length) { var notVisited = points.Where(p => !alreadyVisited.Contains(p.Id)).ToArray(); var next = notVisited.Aggregate(notVisited.First(), (min, curr) => curr.DistanceFrom(last) < min.DistanceFrom(last) ? curr : min); if (next.Y < solution.LastItem.Y) { //i went down, so is there only 1 left above me? var above = points.Where(p => !alreadyVisited.Contains(p.Id) && p != next && p.Y > next.Y).ToArray(); if (above.Length == 1) { var theAbove = above.Single(); if (next.DistanceFrom(last) / theAbove.DistanceFrom(last) > .95) next = theAbove; } } else { //i went up, so is there only 1 left below me? var below = points.Where(p => !alreadyVisited.Contains(p.Id) && p != next && p.Y < next.Y).ToArray(); if (below.Length == 1) { var theBelow = below.Single(); if (next.DistanceFrom(last) / theBelow.DistanceFrom(last) > .95) next = theBelow; } } alreadyVisited.Add(next.Id); last = next; solution.AddNext(next); } }
protected bool Equals(TsPoint other) { return Id == other.Id; }
public double DistanceFrom(TsPoint point) { return Math.Sqrt(Math.Pow(point.X - X, 2) + Math.Pow(point.Y - Y, 2)); }
public TspSolution Execute(TsPoint[] points) { var firstPoint = points.First(); var solution = new TspSolution(firstPoint); //var alreadyVisited = new List<int> { firstPoint.Id }; var notVisited = new List<TsPoint>(points.Where(p => p.Id != firstPoint.Id)); var last = firstPoint; //while (alreadyVisited.Count != points.Length) while(notVisited.Any()) { //var notVisited = points.Where(p => !alreadyVisited.Contains(p.Id)).ToArray(); var next = GetClosestPoint(last, notVisited); //var nextNotVisited = points.Where(p => !alreadyVisited.Contains(p.Id) && p != next).ToArray(); //check for potential orphans var pointsAbove = notVisited.Where(p => p != next && p.Y > last.Y).ToArray(); var pointsBelow = notVisited.Where(p => p != next && p.Y < last.Y).ToArray(); var pointsRight = notVisited.Where(p => p != next && p.X > last.X).ToArray(); var pointsLeft = notVisited.Where(p => p != next && p.X < last.X).ToArray(); TsPoint theAbove = null; TsPoint theBelow = null; TsPoint theRight = null; TsPoint theLeft = null; if (pointsAbove.Length == 1) { theAbove = pointsAbove.Single(); if (next.DistanceFrom(last) / theAbove.DistanceFrom(last) < _threshold) theAbove = null; } if (pointsBelow.Length == 1) { theBelow = pointsBelow.Single(); if (next.DistanceFrom(last) / theBelow.DistanceFrom(last) < _threshold) theBelow = null; } if (pointsRight.Length == 1) { theRight = pointsRight.Single(); if (next.DistanceFrom(last) / theRight.DistanceFrom(last) < _threshold) theRight = null; } if (pointsLeft.Length == 1) { theLeft = pointsLeft.Single(); if (next.DistanceFrom(last) / theLeft.DistanceFrom(last) < _threshold) theLeft = null; } var nextPoints = new[] {theAbove, theBelow, theRight, theLeft}.Where(p => p != null).ToList(); if (nextPoints.Any()) { var unOrphaned = GetClosestPoint(last, nextPoints); //alreadyVisited.Add(unOrphaned.Id); notVisited.Remove(unOrphaned); last = unOrphaned; solution.AddNext(unOrphaned); } else { //alreadyVisited.Add(next.Id); notVisited.Remove(next); last = next; solution.AddNext(next); } } solution.Close(); //solution.OutputToDebug(); return solution; }
public void AddNext(TsPoint point) { var distanceFromLast = point.DistanceFrom(_points.Last()); Distance += distanceFromLast; _points.Add(point); }
public void AddLast(TsPoint point) { AddNext(point); var distanceToBeginning = point.DistanceFrom(_points.First()); Distance += distanceToBeginning; }
public TspSolution(TsPoint firstPoint) { _points = new List<TsPoint> { firstPoint }; }