26 using System.Collections.Generic;
38 public static double GetTourCost<TNode>(IEnumerable<TNode> tour, Func<TNode, TNode, double> cost)
43 TNode prev = tour.First();
44 foreach (var node
in tour.Skip(1))
46 result += cost(prev, node);
56 public interface ITsp<TNode>
60 IEnumerable<TNode> Tour {
get; }
62 double TourCost {
get; }
71 public sealed
class CheapestLinkTsp<TNode> : ITsp<TNode>
75 public IList<TNode> Nodes {
get;
private set; }
77 public Func<TNode, TNode, double> Cost {
get;
private set; }
79 private List<TNode> tour;
80 public IEnumerable<TNode> Tour {
get {
return tour; } }
81 public double TourCost {
get;
private set; }
83 public CheapestLinkTsp(IList<TNode> nodes, Func<TNode, TNode, double> cost)
87 tour =
new List<TNode>();
96 Func<Arc, double> arcCost = (arc => Cost(Nodes[graph.
GetNodeIndex(graph.
U(arc))],
98 Kruskal<double> kruskal =
new Kruskal<double>(graph, arcCost, _ => 2);
101 Dictionary<Node, Arc> firstArc =
new Dictionary<Node, Arc>();
102 Dictionary<Node, Arc> secondArc =
new Dictionary<Node, Arc>();
103 foreach (var arc
in kruskal.Forest)
105 var u = graph.U(arc);
106 (firstArc.ContainsKey(u) ? secondArc : firstArc)[u] = arc;
107 var v = graph.V(arc);
108 (firstArc.ContainsKey(v) ? secondArc : firstArc)[v] = arc;
111 foreach (var startNode
in graph.Nodes())
113 if (kruskal.Degree[startNode] == 1)
115 Arc prevArc = Arc.Invalid;
119 tour.Add(Nodes[graph.GetNodeIndex(n)]);
120 if (prevArc != Arc.Invalid && kruskal.Degree[n] == 1)
break;
121 Arc arc1 = firstArc[n];
122 prevArc = (arc1 != prevArc ? arc1 : secondArc[n]);
123 n = graph.Other(prevArc, n);
125 tour.Add(Nodes[graph.GetNodeIndex(startNode)]);
130 TourCost = TspUtils.GetTourCost(tour, Cost);
148 public sealed
class InsertionTsp<TNode> : ITsp<TNode>
151 public IEnumerable<TNode> Nodes {
get;
private set; }
153 public Func<TNode, TNode, double> Cost {
get;
private set; }
157 private LinkedList<TNode> tour;
159 private Dictionary<TNode, LinkedListNode<TNode>> tourNodes;
161 private HashSet<TNode> insertableNodes;
163 private PriorityQueue<TNode, double> insertableNodeQueue;
169 public IEnumerable<TNode> Tour {
get {
return tour; } }
170 public double TourCost {
get;
private set; }
172 public InsertionTsp(IEnumerable<TNode> nodes, Func<TNode, TNode, double> cost,
177 SelectionRule = selectionRule;
179 tour =
new LinkedList<TNode>();
180 tourNodes =
new Dictionary<TNode,LinkedListNode<TNode>>();
181 insertableNodes =
new HashSet<TNode>();
182 insertableNodeQueue =
new PriorityQueue<TNode, double>();
187 private double PriorityFromCost(
double c)
189 switch (SelectionRule)
202 insertableNodes.Clear();
203 insertableNodeQueue.Clear();
207 TNode startNode = Nodes.First();
208 tour.AddFirst(startNode);
209 tourNodes[startNode] = tour.AddFirst(startNode);
210 foreach (var node
in Nodes)
211 if (!node.Equals(startNode))
213 insertableNodes.Add(node);
214 insertableNodeQueue[node] = PriorityFromCost(Cost(startNode, node));
221 public bool Insert(TNode node)
223 if (!insertableNodes.Contains(node))
return false;
224 insertableNodes.Remove(node);
225 insertableNodeQueue.Remove(node);
228 LinkedListNode<TNode> insertAfter = null;
229 double bestIncrease =
double.PositiveInfinity;
230 for (var llnode = tour.First; llnode != tour.Last; llnode = llnode.Next)
232 var llnode2 = llnode.Next;
233 double increase = Cost(llnode.Value, node) + Cost(node, llnode2.Value);
234 if (llnode != llnode2) increase -= Cost(llnode.Value, llnode2.Value);
235 if (increase < bestIncrease)
237 bestIncrease = increase;
238 insertAfter = llnode;
242 LinkedListNode<TNode> llnodeNew = tourNodes[node] = tour.AddAfter(insertAfter, node);
243 TourCost += bestIncrease;
246 foreach (var n
in insertableNodes)
248 double newPriority = PriorityFromCost(Cost(node, n));
249 if (newPriority < insertableNodeQueue[n]) insertableNodeQueue[n] = newPriority;
259 if (insertableNodes.Count == 0)
return false;
260 Insert(insertableNodeQueue.Peek());
276 public sealed
class Opt2Tsp<TNode> : ITsp<TNode>
279 public Func<TNode, TNode, double> Cost {
get;
private set; }
281 private List<TNode> tour;
283 public IEnumerable<TNode> Tour {
get {
return tour; } }
284 public double TourCost {
get;
private set; }
291 public Opt2Tsp(Func<TNode, TNode, double> cost, IEnumerable<TNode> tour,
double? tourCost)
294 this.tour = tour.ToList();
295 TourCost = tourCost ??
TspUtils.GetTourCost(tour, cost);
302 bool improved =
false;
303 for (
int i = 0; i < tour.Count-3; i++)
305 for (
int j = i + 2, jmax = tour.Count - (i == 0 ? 2 : 1); j < jmax; j++)
307 double increase = Cost(tour[i], tour[j]) + Cost(tour[i+1], tour[j+1]) -
308 (Cost(tour[i], tour[i+1]) + Cost(tour[j], tour[j+1]));
311 TourCost += increase;
312 tour.Reverse(i + 1, j - i);
353 Func<Node, Node, double> cost = (u, v) => (
Graph.
Arcs(u, v,
ArcFilter.Forward).Any() ? 1 : 10);
354 IEnumerable<Node> tour = null;
358 InsertionTsp<Node> insertionTsp =
new InsertionTsp<Node>(
Graph.
Nodes(), cost);
360 if (insertionTsp.TourCost == minimumTourCost) tour = insertionTsp.Tour;
363 Opt2Tsp<Node> opt2Tsp =
new Opt2Tsp<Node>(cost, insertionTsp.Tour, insertionTsp.TourCost);
365 if (opt2Tsp.TourCost == minimumTourCost) tour = opt2Tsp.Tour;
369 if (tour == null)
Cycle = null;
372 var cycle =
new Path(
Graph);
375 Node prev = Node.Invalid;
376 foreach (var n
in tour)
378 if (prev == Node.Invalid) cycle.Begin(n);