Project

General

Profile

root / branches / compiler / cSharp / ooasCompiler / src / libs / c5 / UserGuideExamples / Graph.cs @ 3

1
/*
2
 Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
3
 Permission is hereby granted, free of charge, to any person obtaining a copy
4
 of this software and associated documentation files (the "Software"), to deal
5
 in the Software without restriction, including without limitation the rights
6
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
 copies of the Software, and to permit persons to whom the Software is
8
 furnished to do so, subject to the following conditions:
9
 
10
 The above copyright notice and this permission notice shall be included in
11
 all copies or substantial portions of the Software.
12
 
13
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
 SOFTWARE.
20
*/
21

    
22
// C5 example: Graph representation with basic algorithms using C5 
23

    
24

    
25
// Compile with 
26
//   csc /r:C5.dll Graph.cs 
27

    
28

    
29
// The code is structured as a rudimentary Graph library, with an interface
30
// for (edge)weighted graphs and a single implementation based on an
31
// adjacency list representation using hash dictionaries. 
32

    
33

    
34
// The algorithms implemented include:
35
//
36
// Breadth-First-Search and Depth-First-Search, with an interface based on actions
37
// to be taken as edges are traversed. Applications are checking for connectedness,
38
// counting components
39
//
40
// Priority-First-Search, where edges are traversed according to either weight or 
41
// accumulated weight from the start of the search.
42
// An application of the non-accumulating version is the construction of a minimal
43
// spanning tree and therefore the following approximation algorithm. 
44
// Applications of the accumulating version are the construction of a shortest path
45
// and the computation of the distance from one vertex to another one.
46
//
47
// An approximation algorithm for Travelling Salesman Problems, 
48
// where the weights satisfies the triangle inequality. 
49

    
50

    
51
// Pervasive generic parameters:
52
//                      V: The type of a vertex in a graph. Vertices are identified
53
//                         by the Equals method inherited from object (or overridden).
54
//                      E: The type of additional data associated with edges in a graph.
55
//                      W: The type of values of weights on edges in a weighted graph, 
56
//                         in practise usually int or double. Must be comparable and 
57
//                         there must be given a compatible way to add values.
58
           
59
// Interfaces:
60
//                      IGraph<V,E,W>: The interface for a graph implementation with
61
//                         vertex type V, edge dat type E and weight values of type W.           
62
//                      IWeight<E,W>: The interface of a weight function 
63

    
64
// Classes:
65
//                      HashGraph<V,E,W>: An implementation of IWeightedGraph<V,E,W> based on 
66
//                          adjacency lists represented as hash dictionaries.
67
//                      HashGraph<V,E,W>.EdgesValue: A helper class for the Edges() method
68
//                      CountWeight<E>: A 
69
//                      IntWeight:
70
//                      DoubleWeight:
71

    
72
// Value Types:
73
//                      Edge<V,E>: 
74
//                      EdgeAction<V,E,U>:
75

    
76
// Some notes:
77
// The code only supports "natural" equality of vertices.
78

    
79
using C5;
80
using System;
81
using SCG = System.Collections.Generic;
82

    
83
namespace Graph
84
{
85
  /// <summary>
86
  /// (Duer ikke)
87
  /// </summary>
88
  /// <typeparam name="V"></typeparam>
89
  /// <typeparam name="E"></typeparam>
90
  interface IGraphVertex<V, E,W> where W : IComparable<W>
91
  {
92
    V Value { get;}
93
    IGraph<V, E, W> Graph { get;}
94
    ICollectionValue<KeyValuePair<V, E>> Adjacent { get;}
95

    
96
  }
97

    
98
  class Vertex<V>
99
  {
100
    //V v;
101
  }
102
/// <summary>
103
/// 
104
/// </summary>
105
/// <typeparam name="V"></typeparam>
106
/// <typeparam name="E"></typeparam>
107
/// <typeparam name="W"></typeparam>
108
  interface IGraph<V, E, W> where W : IComparable<W>
109
  {
110
    /// <summary>
111
    /// 
112
    /// </summary>
113
    /// <value>The weight object for this graph</value>
114
    IWeight<E, W> Weight { get;}
115

    
116
    /// <summary>
117
    /// 
118
    /// </summary>
119
    /// <value>The number of vertices in this graph</value>
120
    int VertexCount { get;}
121

    
122
    /// <summary>
123
    /// 
124
    /// </summary>
125
    /// <value>The number of edges in this graph</value>
126
    int EdgeCount { get;}
127

    
128
    /// <summary>
129
    /// The collection of vertices of this graph.
130
    /// The return value is a snapshot, not a live view onto the graph.
131
    /// </summary>
132
    /// <returns></returns>
133
    ICollectionValue<V> Vertices();
134

    
135
    /// <summary>
136
    /// The collection of edges incident to a particular vertex.
137
    /// The return value is a snapshot og (endvertex, edgedata) pairs.
138
    /// </summary>
139
    /// <param name="vertex"></param>
140
    /// <returns></returns>
141
    ICollectionValue<KeyValuePair<V, E>> Adjacent(V vertex);
142

    
143
    /// <summary>
144
    /// The collection of all edges in the graph. The return value is a snapshot
145
    /// of Edge values. Each edge is present once for an undefined direction.
146
    /// </summary>
147
    /// <returns></returns>
148
    ICollectionValue<Edge<V, E>> Edges();
149

    
150
    /// <summary>
151
    /// Add a(n isolated) vertex to the graph Ignore if vertex is already in the graph.
152
    /// </summary>
153
    /// <param name="vertex"></param>
154
    /// <returns>True if the vertex was added.</returns>
155
    bool AddVertex(V vertex);
156

    
157
    /// <summary>
158
    /// Add an edge to the graph. If the edge is already in the graph, update the 
159
    /// edge data. Add vertices as needed.
160
    /// </summary>
161
    /// <param name="start"></param>
162
    /// <param name="end"></param>
163
    /// <param name="edgedata"></param>
164
    /// <returns>True if the edge was added</returns>
165
    bool AddEdge(V start, V end, E edgedata);
166

    
167
    /// <summary>
168
    /// Remove a vertex and all its incident edges from the graph.
169
    /// </summary>
170
    /// <returns>True if the vertex was already in the graph and hence was removed</returns>
171
    bool RemoveVertex(V vertex);
172

    
173
    /// <summary>
174
    /// Remove an edge from the graph. Do not remove the vertices if they become isolated.
175
    /// </summary>
176
    /// <param name="start"></param>
177
    /// <param name="end"></param>
178
    /// <param name="edgedata">On output, the edge data associated with the removed edge.</param>
179
    /// <returns>True if </returns>
180
    bool RemoveEdge(V start, V end, out E edgedata);
181

    
182
    /// <summary>
183
    /// Is there an edge from start to end in this graph, and if so, what is 
184
    /// the data on that edge.
185
    /// </summary>
186
    /// <param name="start"></param>
187
    /// <param name="end"></param>
188
    /// <param name="edge"></param>
189
    /// <returns></returns>
190
    bool FindEdge(V start, V end, out E edge);
191

    
192
    /// <summary>
193
    /// Construct the subgraph corresponding to a set of vertices.
194
    /// </summary>
195
    /// <param name="vs"></param>
196
    /// <returns></returns>
197
    IGraph<V, E, W> SubGraph(ICollectionValue<V> vs);
198

    
199
    /// <summary>
200
    /// 
201
    /// </summary>
202
    /// <value>True if graph is connected</value>
203
    bool IsConnected { get; }
204

    
205
    /// <summary>
206
    /// 
207
    /// </summary>
208
    /// <value>The number of connected components of this graph</value>
209
    int ComponentCount { get;}
210

    
211
    /// <summary>
212
    /// Compute the connnected components of this graph. 
213
    /// </summary>
214
    /// <returns>A collection of (vertex,component) pairs, where the first part of the
215
    /// pair is some vertex in the component.</returns>
216
    ICollectionValue<KeyValuePair<V, IGraph<V, E, W>>> Components();
217

    
218
    /// <summary>
219
    /// Traverse the connected component containing the <code>start</code> vertex, 
220
    /// in either BFS or DFS order, beginning at <code>start</code> and performing the action 
221
    /// <code>act</code> on each edge part of the constructed tree.
222
    /// </summary>
223
    /// <param name="bfs">True if BFS, false if DFS</param>
224
    /// <param name="start">The vertex to start at</param>
225
    /// <param name="act">The action to perform at each node</param>
226
    void TraverseVertices(bool bfs, V start, Action<Edge<V, E>> act);
227

    
228
    /// <summary>
229
    /// Traverse an undirected graph in either BFS or DFS order, performing the action 
230
    /// <code>act</code> on each vertex. 
231
    /// The start vertex of each component of the graph is undefinded. 
232
    /// </summary>
233
    /// <param name="bfs">True if BFS, false if DFS</param>
234
    /// <param name="act"></param>
235
    void TraverseVertices(bool bfs, Action<V> act);
236

    
237
    /// <summary>
238
    /// Traverse an undirected graph in either BFS or DFS order, performing the action 
239
    /// <code>act</code> on each edge in the traversal and beforecomponent/aftercomponent 
240
    /// at the start and end of each component (with argument: the start vertex of the component).
241
    /// </summary>
242
    /// <param name="bfs">True if BFS, false if DFS</param>
243
    /// <param name="act"></param>
244
    /// <param name="beforecomponent"></param>
245
    /// <param name="aftercomponent"></param>
246
    void TraverseVertices(bool bfs, Action<Edge<V, E>> act, Action<V> beforecomponent, Action<V> aftercomponent);
247

    
248
    /// <summary>
249
    /// A more advanced Depth First Search traversal.
250
    /// </summary>
251
    /// <param name="start">The vertex to start the search at</param>
252
    /// <param name="beforevertex">Action to perform when a vertex is first encountered.</param>
253
    /// <param name="aftervertex">Action to perform when all edges out of a vertex has been handles.</param>
254
    /// <param name="onfollow">Action to perform as an edge is traversed.</param>
255
    /// <param name="onfollowed">Action to perform when an edge is travesed back.</param>
256
    /// <param name="onnotfollowed">Action to perform when an edge (a backedge)is seen, but not followed.</param>
257
    void DepthFirstSearch(V start, Action<V> beforevertex, Action<V> aftervertex,
258
            Action<Edge<V, E>> onfollow, Action<Edge<V, E>> onfollowed, Action<Edge<V, E>> onnotfollowed);
259

    
260
    //TODO: perhaps we should avoid exporting this?
261
    /// <summary>
262
    /// Traverse the part of the graph reachable from start in order of least distance 
263
    /// from start according to the weight function. Perform act on the edges of the 
264
    /// traversal as they are recognised.
265
    /// </summary>
266
    /// <typeparam name="W"></typeparam>
267
    /// <param name="weight"></param>
268
    /// <param name="start"></param>
269
    /// <param name="act"></param>
270
    void PriorityFirstTraverse(bool accumulating, V start, EdgeAction<V, E, W> act);
271

    
272
    /// <summary>
273
    /// Compute the (a) shortest path from start to end. THrow an exception if end cannot be reached rom start.
274
    /// </summary>
275
    /// <param name="weight"></param>
276
    /// <param name="start"></param>
277
    /// <param name="end"></param>
278
    /// <returns></returns>
279
    ICollectionValue<Edge<V, E>> ShortestPath(V start, V end);
280

    
281
    /// <summary>
282
    /// Compute the Distance from start to end, i.e. the total weight of a shortest path from start to end. 
283
    /// Throw an exception if end cannot be reached rom start.
284
    /// </summary>
285
    /// <param name="start"></param>
286
    /// <param name="end"></param>
287
    /// <returns></returns>
288
    W Distance(V start, V end);
289

    
290
    /// <summary>
291
    /// Compute a minimum spanning tree for the graph.
292
    /// Throw an exception if this graph is not connected.
293
    /// </summary>
294
    /// <param name="root">(The starting point of the PFS, to be removed)</param>
295
    /// <returns></returns>
296
    IGraph<V, E, W> MinimumSpanningTree(out V root);
297

    
298
    /// <summary>
299
    /// Compute a factor 2 approximation to a Minimum Weight
300
    /// Perfect Matching in a graph using NNs
301
    /// </summary>
302
    /// <returns></returns>
303
    ICollectionValue<Edge<V, E>> ApproximateMWPM();
304

    
305
    /// <summary>
306
    /// Construct a closed Euler tour of this graph if one exists, i.e. if 
307
    /// the graph is connected and all vertices have even degrees. Throw an
308
    /// ArgumentException if no closed Euler tour exists.
309
    /// </summary>
310
    /// <returns>A list of vertices in an Euler tour of this graph.</returns>
311
    IList<V> EulerTour();
312

    
313
    /// <summary>
314
    /// This is intended for implementations of the very simple factor 2 approximation
315
    /// algorithms for the travelling salesman problem for Euclidic weight/distance 
316
    /// functions, i.e. distances that satisfy the triangle inequality. (We do not do 3/2)
317
    /// </summary>
318
    /// <returns></returns>
319
    IDirectedCollectionValue<V> ApproximateTSP();
320

    
321
    /// <summary>
322
    /// Pretty-print the graph to the console (for debugging purposes).
323
    /// </summary>
324
    void Print(System.IO.TextWriter output);
325
  }
326

    
327
/// <summary>
328
/// The type of an edge in a graph. An edge is identified by its pair of 
329
/// vertices. The pair is considered ordered, and so an Edge really describes
330
/// an edge of the graph in a particular traversal direction.
331
/// </summary>
332
/// <typeparam name="V">The type of a vertex.</typeparam>
333
/// <typeparam name="E">The type of data asociated with edges.</typeparam>
334
  struct Edge<V, E>
335
  {
336
    static SCG.IEqualityComparer<V> vequalityComparer = EqualityComparer<V>.Default;
337
    public readonly V start, end;
338
    public readonly E edgedata;
339
    public Edge(V start, V end, E edgedata)
340
    {
341
      if (vequalityComparer.Equals(start, end))
342
        throw new ArgumentException("Illegal: start and end are equal");
343
      this.start = start; this.end = end; this.edgedata = edgedata;
344
    }
345

    
346
    public Edge<V, E> Reverse()
347
    {
348
      return new Edge<V, E>(end, start, edgedata);
349
    }
350

    
351
    public override string ToString()
352
    {
353
      return String.Format("(start='{0}', end='{1}', edgedata='{2}')", start, end, edgedata); ;
354
    }
355

    
356
    public override bool Equals(object obj)
357
    {
358
      if (obj is Edge<V, E>)
359
      {
360
        Edge<V, E> other = (Edge<V, E>)obj;
361
        return vequalityComparer.Equals(start, other.start) && vequalityComparer.Equals(end, other.end);
362
      }
363
      return false;
364
    }
365

    
366
    /// <summary>
367
    /// 
368
    /// </summary>
369
    /// <returns></returns>
370
    public override int GetHashCode()
371
    {
372
      //TODO: should we use xor? Or a random factor?
373
      return start.GetHashCode() + 148712671 * end.GetHashCode();
374
    }
375

    
376
    /// <summary>
377
    /// The unordered equalityComparer compares edges independent of the order of the vertices.
378
    /// </summary>
379
    public class UnorderedEqualityComparer : SCG.IEqualityComparer<Edge<V, E>>
380
    {
381
      /// <summary>
382
      /// Check if two edges have the same vertices irrespective of order.
383
      /// </summary>
384
      /// <param name="i1"></param>
385
      /// <param name="i2"></param>
386
      /// <returns></returns>
387
      public bool Equals(Edge<V, E> i1, Edge<V, E> i2)
388
      {
389
        return (vequalityComparer.Equals(i1.start, i2.start) && vequalityComparer.Equals(i1.end, i2.end)) ||
390
            (vequalityComparer.Equals(i1.end, i2.start) && vequalityComparer.Equals(i1.start, i2.end));
391
      }
392

    
393
      /// <summary>
394
      /// Return a hash code compatible with the unordered equals.
395
      /// </summary>
396
      /// <param name="item"></param>
397
      /// <returns></returns>
398
      public int GetHashCode(Edge<V, E> item)
399
      {
400
        return item.start.GetHashCode() ^ item.end.GetHashCode();
401
      }
402
    }
403
  }
404

    
405
/// <summary>
406
/// The type of the weight object of a graph. This consists of a function mapping
407
/// edge data values to weight values, and an operation to add two weight values.
408
/// It is required that weight values are comparable.
409
/// 
410
/// The user must assure that the add operation is commutative and fulfills 
411
/// Add(w1,w2) &le; w1 for all w1 and w2 that can appear as weights or sums of
412
/// weights. In practise, W will be int or double, all weight values will be 
413
/// non-negative and the addition will be the natural addition on W.
414
/// </summary>
415
/// <typeparam name="E"></typeparam>
416
/// <typeparam name="W"></typeparam>
417
  interface IWeight<E, W> where W : IComparable<W>
418
  {
419
    /// <summary>
420
    /// Compute the weight value corresponding to specific edge data.
421
    /// </summary>
422
    /// <param name="edgedata"></param>
423
    /// <returns></returns>
424
    W Weight(E edgedata);
425

    
426
    /// <summary>
427
    /// Add two weight values.
428
    /// </summary>
429
    /// <param name="w1"></param>
430
    /// <param name="w2"></param>
431
    /// <returns></returns>
432
    W Add(W w1, W w2);
433
  }
434

    
435
/// <summary>
436
/// An action to perform when an edge is encountered during a traversal of the graph.
437
/// The "extra" parameter is for additional information supplied by the traversal 
438
/// algorithm. 
439
/// The intention of the bool return value is that returning false is a signal to the
440
/// traversal algorithm to abandon the traversl because the user has already found
441
/// what he was looking for.
442
/// </summary>
443
/// <typeparam name="V"></typeparam>
444
/// <typeparam name="E"></typeparam>
445
/// <typeparam name="U"></typeparam>
446
/// <param name="edge"></param>
447
/// <param name="extra"></param>
448
/// <returns></returns>
449
  delegate bool EdgeAction<V, E, U>(Edge<V, E> edge, U extra);
450

    
451

    
452
/*
453
  For a dense graph, we would use data fields:
454

    
455
  E'[,] or E'[][] for the matrix. Possibly E'[][] for a triangular one!
456
  Here E' = struct{E edgedata, bool present} or class{E edgedata}, or if E is a class just E.
457
  Thus E' is E! for value types. Or we could have two matrices: E[][] and bool[][]. 
458

    
459
  HashDictionary<V,int> to map vertex ids to indices.
460
  ArrayList<V> for the map the other way.
461
  Or simply a HashedArrayList<V> to get both?
462

    
463
  PresentList<int>, FreeList<int> or similar, if we do not want to compact the indices in the matrix on each delete.
464
  If we compact, we always do a delete on the vertex<->index map by a replace and a removelast:
465
    vimap[ind]=vimap[vimap.Count]; vimap.RemoveLast(); //also reorder matrix!
466
  
467

    
468
*/
469

    
470
/// <summary>
471
/// An implementation of IGraph&le;V,E,W&ge; based on an adjacency list representation using hash dictionaries.
472
/// As a consequence, this will be most efficient for sparse graphs.
473
/// </summary>
474
/// <typeparam name="V"></typeparam>
475
/// <typeparam name="E"></typeparam>
476
/// <typeparam name="W"></typeparam>
477
  class HashGraph<V, E, W> : IGraph<V, E, W> where W : IComparable<W>
478
  {
479
    int edgecount;
480

    
481
    HashDictionary<V, HashDictionary<V, E>> graph;
482

    
483
    IWeight<E, W> weight;
484

    
485
    public IWeight<E, W> Weight { get { return weight; } }
486

    
487

    
488
    /// <summary>
489
    /// Create an initially empty graph.
490
    /// </summary>
491
    /// <param name="weight"></param>
492
    [UsedBy("testTSP")]
493
    public HashGraph(IWeight<E, W> weight)
494
    {
495
      this.weight = weight;
496
      edgecount = 0;
497
      graph = new HashDictionary<V, HashDictionary<V, E>>();
498
    }
499

    
500
    /// <summary>
501
    /// Constructing a graph with no isolated vertices given a collection of edges.
502
    /// </summary>
503
    /// <param name="edges"></param>
504
    [UsedBy()]
505
    public HashGraph(IWeight<E, W> weight, SCG.IEnumerable<Edge<V, E>> edges) : this(weight)
506
    {
507
      foreach (Edge<V, E> edge in edges)
508
      {
509
        if (edge.start.Equals(edge.end))
510
          throw new ApplicationException("Edge has equal start and end");
511
        {
512
          HashDictionary<V, E> edgeset;
513
          //TODO: utilize upcoming FindOrAddSome operation
514
          if (!graph.Find(edge.start, out edgeset))
515
            graph.Add(edge.start, edgeset = new HashDictionary<V, E>());
516
          if (!edgeset.UpdateOrAdd(edge.end, edge.edgedata))
517
            edgecount++;
518
          if (!graph.Find(edge.end, out edgeset))
519
            graph.Add(edge.end, edgeset = new HashDictionary<V, E>());
520
          edgeset.UpdateOrAdd(edge.start, edge.edgedata);
521
        }
522
      }
523
    }
524

    
525
    /// <summary>
526
    /// This constructs a graph with a given set of vertices.
527
    /// Will only allow these vertices.
528
    /// Duplicate edges are allowed.
529
    /// </summary>
530
    /// <param name="vertices"></param>
531
    /// <param name="edges"></param>
532
    public HashGraph(IWeight<E, W> weight, SCG.IEnumerable<V> vertices, SCG.IEnumerable<Edge<V, E>> edges) : this(weight)
533
    {
534
      foreach (V v in vertices)
535
        graph.Add(v, new HashDictionary<V, E>());
536
      foreach (Edge<V, E> edge in edges)
537
      {
538
        HashDictionary<V, E> edgeset;
539
        if (edge.start.Equals(edge.end))
540
          throw new ApplicationException("Edge has equal start and end");
541
        if (!graph.Find(edge.start, out edgeset))
542
          throw new ApplicationException("Edge has unknown start");
543
        if (!edgeset.UpdateOrAdd(edge.end, edge.edgedata))
544
          edgecount++;
545
        if (!graph.Find(edge.end, out edgeset))
546
          throw new ApplicationException("Edge has unknown end");
547
        edgeset.UpdateOrAdd(edge.start, edge.edgedata);
548
      }
549
    }
550

    
551
    [UsedBy("testCOMP")]
552
    public int VertexCount { get { return graph.Count; } }
553

    
554
    [UsedBy("testCOMP")]
555
    public int EdgeCount { get { return edgecount; } }
556

    
557
    public ICollectionValue<V> Vertices()
558
    {
559
      return new GuardedCollectionValue<V>(graph.Keys);
560
    }
561

    
562
    public ICollectionValue<KeyValuePair<V, E>> Adjacent(V vertex)
563
    {
564
      return new GuardedCollectionValue<KeyValuePair<V, E>>(graph[vertex]);
565
    }
566

    
567
    class EdgesValue : CollectionValueBase<Edge<V, E>>
568
    {
569
      HashGraph<V, E, W> graph;
570
      internal EdgesValue(HashGraph<V, E, W> g) { graph = g; }
571

    
572
      public override bool IsEmpty { get { return graph.edgecount == 0; } }
573

    
574
      public override int Count { get { return graph.edgecount; } }
575

    
576
      public override Speed CountSpeed { get { return Speed.Constant; } }
577

    
578

    
579
      public override Edge<V, E> Choose()
580
      {
581
        KeyValuePair<V, HashDictionary<V, E>> adjacent = graph.graph.Choose();
582
        KeyValuePair<V, E> otherend = graph.graph[adjacent.Key].Choose();
583
        return new Edge<V, E>(adjacent.Key, otherend.Key, otherend.Value);
584
      }
585

    
586
      public override SCG.IEnumerator<Edge<V, E>> GetEnumerator()
587
      {
588
        HashSet<Edge<V, E>> seen = new HashSet<Edge<V, E>>(new Edge<V, E>.UnorderedEqualityComparer());
589
        foreach (V v in graph.graph.Keys)
590
          foreach (KeyValuePair<V, E> p in graph.graph[v])
591
          {
592
            Edge<V, E> edge = new Edge<V, E>(v, p.Key, p.Value);
593
            if (!seen.FindOrAdd(ref edge))
594
              yield return edge;
595
          }
596
      }
597
    }
598

    
599
    public ICollectionValue<Edge<V, E>> Edges()
600
    {
601
      return new EdgesValue(this);
602
    }
603

    
604
    public bool AddVertex(V v)
605
    {
606
      if (graph.Contains(v))
607
        return false;
608
      graph.Add(v, new HashDictionary<V, E>());
609
      return true;
610
    }
611

    
612
    //Note: no warning on update of edgedata!
613
    //TODO: Shouldn?t Update or Add return the old value?
614
    //Then it would be easy to check for updates 
615
    public bool AddEdge(V start, V end, E edgedata)
616
    {
617
      bool retval = false;
618
      HashDictionary<V, E> edgeset;
619
      if (graph.Find(start, out edgeset))
620
        retval = !edgeset.UpdateOrAdd(end, edgedata);
621
      else
622
      {
623
        graph[start] = edgeset = new HashDictionary<V, E>();
624
        edgeset[end] = edgedata;
625
        retval = true;
626
      }
627
      if (graph.Find(end, out edgeset))
628
        edgeset.UpdateOrAdd(start, edgedata);
629
      else
630
      {
631
        graph[end] = edgeset = new HashDictionary<V, E>();
632
        edgeset[start] = edgedata;
633
      }
634
      if (retval)
635
        edgecount++;
636
      return retval;
637
    }
638

    
639
    public bool RemoveVertex(V vertex)
640
    {
641
      HashDictionary<V, E> edgeset;
642
      if (!graph.Find(vertex, out edgeset))
643
        return false;
644
      foreach (V othervertex in edgeset.Keys)
645
        graph[othervertex].Remove(vertex); //Assert retval==true
646
      edgecount -= edgeset.Count;
647
      graph.Remove(vertex);
648
      return true;
649
    }
650

    
651
    public bool RemoveEdge(V start, V end, out E edgedata)
652
    {
653
      HashDictionary<V, E> edgeset;
654
      if (!graph.Find(start, out edgeset))
655
      {
656
        edgedata = default(E);
657
        return false;
658
      }
659
      if (!edgeset.Remove(end, out edgedata))
660
        return false;
661
      graph[end].Remove(start);
662
      edgecount--;
663
      return true;
664
    }
665

    
666
    public bool FindEdge(V start, V end, out E edgedata)
667
    {
668
      HashDictionary<V, E> edges;
669
      if (!graph.Find(start, out edges))
670
      {
671
        edgedata = default(E);
672
        return false;
673
      }
674
      return edges.Find(end, out edgedata);
675
    }
676

    
677
    public IGraph<V, E, W> SubGraph(ICollectionValue<V> vs)
678
    {
679
      HashSet<V> vertexset = vs as HashSet<V>;
680
      if (vertexset == null)
681
      {
682
        vertexset = new HashSet<V>();
683
        vertexset.AddAll(vs);
684
      }
685

    
686
      return new HashGraph<V, E, W>(weight,
687
          vs,
688
          Edges().Filter(delegate(Edge<V, E> e) { return vertexset.Contains(e.start) && vertexset.Contains(e.end); }));
689
    }
690

    
691
    public bool IsConnected
692
    {
693
      //TODO: optimize: needs to change Action<Edge<V,E>> to EdgeAction to be able to break out
694
      get { return ComponentCount <= 1; }
695
    }
696

    
697
    public int ComponentCount
698
    {
699
      get
700
      {
701
        int components = 0;
702
        TraverseVertices(false, null, delegate(V v) { components++; }, null);
703
        return components;
704
      }
705
    }
706

    
707
    public ICollectionValue<KeyValuePair<V, IGraph<V, E, W>>> Components()
708
    {
709
      ArrayList<KeyValuePair<V, IGraph<V, E, W>>> retval = new ArrayList<KeyValuePair<V, IGraph<V, E, W>>>();
710
      HashGraph<V, E, W> component;
711
      ArrayList<V> vertices = null;
712
      Action<Edge<V, E>> edgeaction = delegate(Edge<V, E> e)
713
      {
714
        vertices.Add(e.end);
715
      };
716
      Action<V> beforecomponent = delegate(V v)
717
      {
718
        vertices = new ArrayList<V>();
719
        vertices.Add(v);
720
      };
721
      Action<V> aftercomponent = delegate(V v)
722
      {
723
        //component = SubGraph(vertices);
724
        component = new HashGraph<V, E, W>(weight);
725
        foreach (V start in vertices)
726
        {
727
          //component.graph[start] = graph[start].Clone();
728
          HashDictionary<V, E> edgeset = component.graph[start] = new HashDictionary<V, E>();
729
          foreach (KeyValuePair<V, E> adjacent in graph[start])
730
            edgeset[adjacent.Key] = adjacent.Value;
731
        }
732
        retval.Add(new KeyValuePair<V, IGraph<V, E, W>>(v, component));
733
      };
734
      TraverseVertices(false, edgeaction, beforecomponent, aftercomponent);
735
      return retval;
736
    }
737

    
738
    [UsedBy("test1")]
739
    public void TraverseVertices(bool bfs, V start, Action<Edge<V, E>> act)
740
    {
741
      if (!graph.Contains(start))
742
        throw new ArgumentException("start Vertex not in graph");
743
      IList<Edge<V, E>> todo = new LinkedList<Edge<V, E>>();
744
      todo.FIFO = bfs;
745
      HashSet<V> seen = new HashSet<V>();
746
      V v;
747
      while (!todo.IsEmpty || seen.Count == 0)
748
      {
749
        if (seen.Count > 1)
750
        {
751
          Edge<V, E> e = todo.Remove();
752
          if (act != null)
753
            act(e);
754
          v = e.end;
755
        }
756
        else
757
        {
758
          seen.Add(start);
759
          v = start;
760
        }
761

    
762
        HashDictionary<V, E> adjacent;
763
        if (graph.Find(v, out adjacent))
764
        {
765
          foreach (KeyValuePair<V, E> p in adjacent)
766
          {
767
            V end = p.Key;
768
            if (!seen.FindOrAdd(ref end))
769
              todo.Add(new Edge<V, E>(v, end, p.Value));
770
          }
771
        }
772
      }
773
    }
774

    
775
    public void TraverseVertices(bool bfs, Action<V> act)
776
    {
777
      TraverseVertices(bfs, delegate(Edge<V, E> e) { act(e.end); }, act, null);
778
    }
779

    
780
    //TODO: merge the hash set here with the intra omponent one?
781
    public void TraverseVertices(bool bfs, Action<Edge<V, E>> act, Action<V> beforecomponent, Action<V> aftercomponent)
782
    {
783
      HashSet<V> missing = new HashSet<V>();
784
      missing.AddAll(Vertices());
785
      Action<Edge<V, E>> myact = act + delegate(Edge<V, E> e) { missing.Remove(e.end); };
786
      Action<V> mybeforecomponent = beforecomponent + delegate(V v) { missing.Remove(v); };
787
      while (!missing.IsEmpty)
788
      {
789
        V start = default(V);
790
        foreach (V v in missing)
791
        { start = v; break; }
792
        mybeforecomponent(start);
793
        TraverseVertices(bfs, start, myact);
794
        if (aftercomponent != null)
795
          aftercomponent(start);
796
      }
797
    }
798

    
799
    delegate void Visitor(V v, V parent, bool atRoot);
800

    
801
    //TODO: allow actions to be null
802
    [UsedBy("testDFS")]
803
    public void DepthFirstSearch(V start, Action<V> before, Action<V> after,
804
        Action<Edge<V, E>> onfollow, Action<Edge<V, E>> onfollowed, Action<Edge<V, E>> onnotfollowed)
805
    {
806
      HashSet<V> seen = new HashSet<V>();
807
      seen.Add(start);
808
      //If we do not first set visit = null, the compiler will complain at visit(end)
809
      //that visit is uninitialized
810
      Visitor visit = null;
811
      visit = delegate(V v, V parent, bool atRoot)
812
      {
813
        before(v);
814
        HashDictionary<V, E> adjacent;
815
        if (graph.Find(v, out adjacent))
816
          foreach (KeyValuePair<V, E> p in adjacent)
817
          {
818
            V end = p.Key;
819
            Edge<V, E> e = new Edge<V, E>(v, end, p.Value);
820
            if (!seen.FindOrAdd(ref end))
821
            {
822
              onfollow(e);
823
              visit(end, v, false);
824
              onfollowed(e);
825
            }
826
            else
827
            {
828
              if (!atRoot && !parent.Equals(end))
829
                onnotfollowed(e);
830
            }
831
          }
832
        after(v);
833
      };
834
      visit(start, default(V), true);
835
    }
836

    
837
    public void PriorityFirstTraverse(bool accumulated, V start, EdgeAction<V, E, W> act)
838
    {
839
      if (!graph.Contains(start))
840
        throw new ArgumentException("Graph does not contain start");
841
      IPriorityQueue<W> fringe = new IntervalHeap<W>();
842
      HashDictionary<V, IPriorityQueueHandle<W>> seen = new HashDictionary<V, IPriorityQueueHandle<W>>();
843
      HashDictionary<IPriorityQueueHandle<W>, Edge<V, E>> bestedge = new HashDictionary<IPriorityQueueHandle<W>, Edge<V, E>>();
844

    
845
      IPriorityQueueHandle<W> h = null;
846
      V current;
847
      W currentdist;
848
      while (!fringe.IsEmpty || seen.Count == 0)
849
      {
850
        if (seen.Count == 0)
851
        {
852
          seen.Add(start, h);
853
          current = start;
854
          currentdist = default(W);
855
        }
856
        else
857
        {
858
          currentdist = fringe.DeleteMin(out h);
859
          Edge<V, E> e = bestedge[h];
860
          if (!act(e, currentdist))
861
            break;
862
          bestedge.Remove(h);
863
          current = e.end;
864
        }
865
        HashDictionary<V, E> adjacentnodes;
866
        if (graph.Find(current, out adjacentnodes))
867
          foreach (KeyValuePair<V, E> adjacent in adjacentnodes)
868
          {
869
            V end = adjacent.Key;
870
            E edgedata = adjacent.Value;
871
            W dist = weight.Weight(edgedata), olddist;
872
            if (accumulated && !current.Equals(start)) dist = weight.Add(currentdist, weight.Weight(edgedata));
873
            if (!seen.Find(end, out h))
874
            {
875
              h = null;
876
              fringe.Add(ref h, dist);
877
              seen[end] = h;
878
              bestedge[h] = new Edge<V, E>(current, end, edgedata);
879
            }
880
            else if (fringe.Find(h, out olddist) && dist.CompareTo(olddist) < 0)
881
            {
882
              fringe[h] = dist;
883
              bestedge[h] = new Edge<V, E>(current, end, edgedata);
884
            }
885
          }
886
      }
887
    }
888

    
889
    public W Distance(V start, V end)
890
    {
891
      W dist = default(W);
892
      bool found = false;
893
      PriorityFirstTraverse(true, start, delegate(Edge<V, E> e, W w)
894
      {
895
        if (end.Equals(e.end)) { dist = w; found = true; return false; }
896
        else return true;
897
      });
898
      if (found)
899
        return dist;
900
      throw new ArgumentException(String.Format("No path from {0} to {1}", start, end));
901
    }
902

    
903

    
904
    public ICollectionValue<Edge<V, E>> ShortestPath(V start, V end)
905
    {
906
      HashDictionary<V, Edge<V, E>> backtrack = new HashDictionary<V, Edge<V, E>>();
907
      PriorityFirstTraverse(true, start, delegate(Edge<V, E> e, W w) { backtrack[e.end] = e; return !end.Equals(e.end); });
908
      ArrayList<Edge<V, E>> path = new ArrayList<Edge<V, E>>();
909
      Edge<V, E> edge;
910
      V v = end;
911
      while (backtrack.Find(v, out edge))
912
      {
913
        path.Add(edge);
914
        v = edge.start;
915
      }
916
      if (path.IsEmpty)
917
        throw new ArgumentException(String.Format("No path from {0} to {1}", start, end));
918
      path.Reverse();
919
      return path;
920
    }
921

    
922
    /// <summary>
923
    /// NB: assume connected, throw exception if not
924
    /// </summary>
925
    /// <typeparam name="W"></typeparam>
926
    /// <param name="edgeWeight"></param>
927
    /// <returns></returns>
928
    public IGraph<V, E, W> MinimumSpanningTree(out V start)
929
    {
930
      ArrayList<Edge<V, E>> edges = new ArrayList<Edge<V, E>>();
931
      start = default(V);
932
      foreach (V v in graph.Keys)
933
      { start = v; break; }
934
      PriorityFirstTraverse(false, start, delegate(Edge<V, E> e, W w) { edges.Add(e); return true; });
935
      if (edges.Count != graph.Count - 1)
936
        throw new ArgumentException("Graph not connected");
937
      return new HashGraph<V, E, W>(weight, edges);
938
    }
939

    
940
    public ICollectionValue<Edge<V, E>> ApproximateMWPM()
941
    {
942
      //Assume graph complete and even number of vertices
943
      HashGraph<V, E, W> clone = new HashGraph<V, E, W>(weight, Edges());
944
      ArrayList<Edge<V, E>> evenpath = new ArrayList<Edge<V, E>>();
945
      ArrayList<Edge<V, E>> oddpath = new ArrayList<Edge<V, E>>();
946
      V start = default(V);
947
      foreach (V v in clone.Vertices()) { start = v; break; }
948
      V current = start;
949
      W evenweight, oddweight;
950
      evenweight = oddweight = default(W);
951
      bool even = true;
952
      while (clone.VertexCount > 0)
953
      {
954
        V bestvertex = default(V);
955
        E bestedge = default(E);
956
        W bestweight = default(W);
957
        if (clone.VertexCount == 1)
958
        {
959
          bestvertex = start;
960
          bestedge = graph[current][start];
961
          bestweight = weight.Weight(bestedge);
962
        }
963
        else
964
        {
965
          bool first = true;
966
          foreach (KeyValuePair<V, E> p in clone.graph[current])
967
          {
968
            W thisweight = weight.Weight(p.Value);
969
            if (first || bestweight.CompareTo(thisweight) > 0)
970
            {
971
              bestvertex = p.Key;
972
              bestweight = thisweight;
973
              bestedge = p.Value;
974
            }
975
            first = false;
976
          }
977
        }
978
        clone.RemoveVertex(current);
979
        //Console.WriteLine("-* {0} / {1} / {2}", bestvertex, bestweight, tour.Count);
980
        if (even)
981
        {
982
          evenweight = evenpath.Count < 1 ? bestweight : weight.Add(evenweight, bestweight);
983
          evenpath.Add(new Edge<V, E>(current, bestvertex, bestedge));
984
        }
985
        else
986
        {
987
          oddweight = oddpath.Count < 1 ? bestweight : weight.Add(oddweight, bestweight);
988
          oddpath.Add(new Edge<V, E>(current, bestvertex, bestedge));
989
        }
990
        current = bestvertex;
991
        even = !even;
992
      }
993
      //Console.WriteLine("Totalweights: even: {0} and odd: {1}", evenweight, oddweight);
994
      return evenweight.CompareTo(oddweight) < 0 ? evenpath : oddpath;
995
    }
996

    
997
    /// <summary>
998
    /// The construction is performed as follows: 
999
    /// Start at some vertex. Greedily construct a path starting there by 
1000
    /// following edges at random until no more unused edges are available
1001
    /// from the current node, which must be the start node. Then follow 
1002
    /// the path constructed so far and whenever we meet a vertex with 
1003
    /// unused edges, construct a path from there greedily as above, 
1004
    /// inserting into the path in front of us.
1005
    /// 
1006
    /// The algorithm will use constant time for each vertex added 
1007
    /// to the path and 
1008
    /// 
1009
    /// Illustrates use of views as a safe version of listnode pointers 
1010
    /// and hashed linked lists for choosing some item in constant time combined 
1011
    /// with (expected) constant time remove.
1012
    /// </summary>
1013
    /// <returns></returns>
1014
    public IList<V> EulerTour()
1015
    {
1016
      bool debug = false;
1017
      //Assert connected and all degrees even. (Connected is checked at the end)
1018
      string fmt = "Graph does not have a closed Euler tour: vertex {0} has odd degree {1}";
1019
      foreach (KeyValuePair<V, HashDictionary<V, E>> adj in graph)
1020
        if (adj.Value.Count % 2 != 0)
1021
          throw new ArgumentException(String.Format(fmt, adj.Key, adj.Value.Count));
1022

    
1023
      LinkedList<V> path = new LinkedList<V>();
1024
      //Clone the graph data to keep track of used edges.
1025
      HashDictionary<V, HashedArrayList<V>> edges = new HashDictionary<V, HashedArrayList<V>>();
1026
      V start = default(V);
1027
      HashedArrayList<V> adjacent = null;
1028
      foreach (KeyValuePair<V, HashDictionary<V, E>> p in graph)
1029
      {
1030
        adjacent = new HashedArrayList<V>();
1031
        adjacent.AddAll(p.Value.Keys);
1032
        start = p.Key;
1033
        edges.Add(start, adjacent);
1034
      }
1035

    
1036
      path.Add(start);
1037
      IList<V> view = path.View(0, 1);
1038
      while (adjacent.Count > 0)
1039
      {
1040
        V current = view[0];
1041
        if (debug) Console.WriteLine("==> {0}", current);
1042
        //Augment the path (randomly) until we return here and all edges
1043
        while (adjacent.Count > 0)
1044
        {
1045
          if (debug) Console.WriteLine(" => {0}, {1}", current, path.Count);
1046
          V next = adjacent.RemoveFirst();
1047
          view.Add(next);
1048
          if (debug) Console.WriteLine("EDGE: " + current + "->" + next);
1049
          if (!edges[next].Remove(current))
1050
            Console.WriteLine("Bad");
1051
          current = next;
1052
          adjacent = edges[current];
1053
        }
1054
        //When we get here, the view contains a closed path, i.e.
1055
        //view[view.Count-1] == view[0] and we have followed all edges from view[0]
1056
        //We slide forward along the rest of the path constructed so far and stop at the
1057
        //first vertex with still unfollwed edges.
1058
        while (view.Offset < path.Count - 1 && adjacent.Count == 0)
1059
        {
1060
          view.Slide(1, 1);
1061
          if (debug) Console.WriteLine(" -> {0}, {1}", view[0], path.Count);
1062
          adjacent = edges[view[0]];
1063
        }
1064
      }
1065
      if (path.Count <= edges.Count)
1066
        throw new ArgumentException("Graph was not connected");
1067
      return path;
1068
    }
1069

    
1070
    /// <summary>
1071
    /// The purpose of this struct is to be able to create and add new,
1072
    /// synthetic vertices to a graph. 
1073
    /// </summary>
1074
    struct Vplus : IEquatable<Vplus>
1075
    {
1076
      internal readonly V vertex; internal readonly int id;
1077
      static SCG.IEqualityComparer<V> vequalityComparer = EqualityComparer<V>.Default;
1078
      internal Vplus(V v) { vertex = v; id = 0; }
1079
      internal Vplus(int i) { vertex = default(V); id = i; }
1080
      //We should override Equals and GetHashCode
1081

    
1082
      public override string ToString()
1083
      { return id == 0 ? String.Format("real({0})", vertex) : String.Format("fake({0})", id); }
1084

    
1085
      public override bool Equals(object obj) { throw new NotImplementedException(); }
1086

    
1087
      public bool Equals(Vplus other) { return vequalityComparer.Equals(vertex, other.vertex) && id == other.id; }
1088

    
1089
      public override int GetHashCode() { return vequalityComparer.GetHashCode(vertex) + id; }
1090
    }
1091

    
1092
    /// <summary>
1093
    /// 
1094
    /// </summary>
1095
    /// <returns></returns>
1096
    public IDirectedCollectionValue<V> ApproximateTSP2()
1097
    {
1098
      /* Construct a minimum spanning tree for the graph */
1099
      V root;
1100
      IGraph<V, E, W> tree = MinimumSpanningTree(out root);
1101

    
1102
      //Console.WriteLine("========= Matching of odd vertices of mst =========");
1103
      ArrayList<V> oddvertices = new ArrayList<V>();
1104
      foreach (V v in tree.Vertices())
1105
        if (tree.Adjacent(v).Count % 2 != 0)
1106
          oddvertices.Add(v);
1107

    
1108
      ICollectionValue<Edge<V, E>> matching = SubGraph(oddvertices).ApproximateMWPM();
1109

    
1110
      //Console.WriteLine("========= Fuse matching and tree =========");
1111
      //We must split the edges of the matching with fake temporary vertices
1112
      //since the matching and the tree may have common edges
1113

    
1114
      HashGraph<Vplus, E, W> fused = new HashGraph<Vplus, E, W>(weight);
1115
      foreach (Edge<V, E> e in tree.Edges())
1116
        fused.AddEdge(new Vplus(e.start), new Vplus(e.end), e.edgedata);
1117
      int fakeid = 1;
1118
      foreach (Edge<V, E> e in matching)
1119
      {
1120
        Vplus fakevertex = new Vplus(fakeid++);
1121
        fused.AddEdge(new Vplus(e.start), fakevertex, e.edgedata);
1122
        fused.AddEdge(fakevertex, new Vplus(e.end), e.edgedata);
1123
      }
1124
      fused.Print(Console.Out);
1125

    
1126
      //Console.WriteLine("========= Remove fake vertices and perform shortcuts =========");
1127
      IList<Vplus> fusedtour = fused.EulerTour();
1128
      HashSet<V> seen = new HashSet<V>();
1129
      IList<V> tour = new ArrayList<V>();
1130

    
1131
      foreach (Vplus vplus in fused.EulerTour())
1132
      {
1133
        V v = vplus.vertex;
1134
        if (vplus.id == 0 && !seen.FindOrAdd(ref v))
1135
          tour.Add(v);
1136
      }
1137
      return tour;
1138
    }
1139

    
1140
    /// <summary>
1141
    /// (Refer to the litterature, Vazirani)
1142
    /// 
1143
    /// (Describe: MST+Euler+shortcuts)
1144
    /// </summary>
1145
    /// <returns></returns>
1146
    [UsedBy("testTSP")]
1147
    public IDirectedCollectionValue<V> ApproximateTSP()
1148
    {
1149
      /* Construct a minimum spanning tree for the graph */
1150
      V root;
1151
      IGraph<V, E, W> tree = MinimumSpanningTree(out root);
1152

    
1153
      /* (Virtually) double all edges of MST and construct an Euler tour of the vertices*/
1154
      LinkedList<V> tour = new LinkedList<V>();
1155
      tour.Add(root);
1156
      tour.Add(root);
1157
      IList<V> view = tour.View(1, 1);
1158

    
1159
      Action<Edge<V, E>> onfollow = delegate(Edge<V, E> e)
1160
      {
1161
        //slide the view until it points to the last copy of e.start
1162
        while (!view[0].Equals(e.start))
1163
          view.Slide(1);
1164
        //then insert two copies of e.end and slide the view one backwards
1165
        view.InsertFirst(e.end);
1166
        view.InsertFirst(e.end);
1167
        view.Slide(1, 1);
1168
      };
1169

    
1170
      tree.TraverseVertices(false, root, onfollow);
1171

    
1172
      /* Finally, slide along the Euler tour and shortcut by removing vertices already seen*/
1173
      HashSet<V> seen = new HashSet<V>();
1174
      view = tour.View(0, tour.Count);
1175
      while (view.Offset < tour.Count - 1)
1176
      {
1177
        V v = view[0];
1178
        if (seen.FindOrAdd(ref v))
1179
          view.RemoveFirst();
1180
        else
1181
          view.Slide(1, view.Count - 1);
1182
      }
1183
      return tour;
1184
    }
1185

    
1186
    public void Print(System.IO.TextWriter output)
1187
    {
1188
      output.WriteLine("Graph has {0} vertices, {1} edges, {2} components", graph.Count, edgecount, ComponentCount);
1189
      foreach (KeyValuePair<V, HashDictionary<V, E>> p in graph)
1190
      {
1191
        output.Write(" {0} ->  ", p.Key);
1192
        foreach (KeyValuePair<V, E> p2 in p.Value)
1193
          output.Write("{1} (data {2}), ", p.Key, p2.Key, p2.Value);
1194
        output.WriteLine();
1195
      }
1196
    }
1197
  }
1198

    
1199
/// <summary>
1200
/// A weight on a graph that assigns the weight 1 to every edge.
1201
/// </summary>
1202
/// <typeparam name="E">(Ignored) type of edgedata</typeparam>
1203
  class CountWeight<E> : IWeight<E, int>
1204
  {
1205
    public int Weight(E edgedata) { return 1; }
1206

    
1207
    public int Add(int w1, int w2) { return w1 + w2; }
1208
  }
1209

    
1210
/// <summary>
1211
/// A weight on an IGraph&lt;V,int&gt; that uses the value of the edgedata as the weight value.
1212
/// </summary>
1213
  class IntWeight : IWeight<int, int>
1214
  {
1215

    
1216
    public int Weight(int edgedata) { return edgedata; }
1217

    
1218
    public int Add(int w1, int w2) { return w1 + w2; }
1219

    
1220
  }
1221

    
1222
/// <summary>
1223
/// A weight on an IGraph&lt;V,double&gt; that uses the value of the edgedata as the weight value.
1224
/// </summary>
1225
  class DoubleWeight : IWeight<double, double>
1226
  {
1227

    
1228
    public double Weight(double edgedata) { return edgedata; }
1229

    
1230
    public double Add(double w1, double w2) { return w1 + w2; }
1231

    
1232
  }
1233

    
1234
/// <summary>
1235
/// Attribute used for marking which examples use a particuler graph method
1236
/// </summary>
1237
  class UsedByAttribute : Attribute
1238
  {
1239
    string[] tests;
1240
    internal UsedByAttribute(params string[] tests) { this.tests = tests; }
1241

    
1242
    public override string ToString()
1243
    {
1244
      System.Text.StringBuilder sb = new System.Text.StringBuilder();
1245
      for (int i = 0; i < tests.Length; i++)
1246
      {
1247
        if (i > 0)
1248
          sb.Append(", ");
1249
        sb.Append(tests[i]);
1250
      }
1251
      return sb.ToString();
1252
    }
1253
  }
1254

    
1255
/// <summary>
1256
/// Attribute for marking example methods with a description
1257
/// </summary>
1258
  class ExampleDescriptionAttribute : Attribute
1259
  {
1260
    string text;
1261
    internal ExampleDescriptionAttribute(string text) { this.text = text; }
1262

    
1263
    public override string ToString() { return text; }
1264
  }
1265

    
1266
/// <summary>
1267
/// A selection of test cases
1268
/// </summary>
1269
  class Test
1270
  {
1271
    static SCG.IEnumerable<Edge<int, int>> Grid(int n)
1272
    {
1273
      Random ran = new Random(1717);
1274
      for (int i = 1; i <= n; i++)
1275
      {
1276
        for (int j = 1; j <= n; j++)
1277
        {
1278
          yield return new Edge<int, int>(1000 * i + j, 1000 * (i + 1) + j, ran.Next(1, 100));
1279
          yield return new Edge<int, int>(1000 * i + j, 1000 * i + j + 1, ran.Next(1, 100));
1280
        }
1281
      }
1282
    }
1283

    
1284
    static SCG.IEnumerable<Edge<string, int>> Snake(int n)
1285
    {
1286
      for (int i = 1; i <= n; i++)
1287
      {
1288
        yield return new Edge<string, int>("U" + i, "L" + i, 1);
1289
        yield return new Edge<string, int>("U" + i, "U" + (i + 1), i % 2 == 0 ? 1 : 10);
1290
        yield return new Edge<string, int>("L" + i, "L" + (i + 1), i % 2 == 0 ? 10 : 1);
1291
      }
1292
    }
1293

    
1294
    /// <summary>
1295
    /// Create the edges of a forest of complete binary trees.
1296
    /// </summary>
1297
    /// <param name="treeCount">Number of trees</param>
1298
    /// <param name="height">Height of trees</param>
1299
    /// <returns></returns>
1300
    static SCG.IEnumerable<Edge<string, int>> Forest(int treeCount, int height)
1301
    {
1302
      for (int i = 0; i < treeCount; i++)
1303
      {
1304
        IList<string> q = new ArrayList<string>();
1305
        string root = String.Format("[{0}]", i);
1306
        int lmax = height + root.Length;
1307
        q.Add(root);
1308
        while (!q.IsEmpty)
1309
        {
1310
          string s = q.Remove();
1311
          string s2 = s + "L";
1312
          if (s2.Length < lmax)
1313
            q.Add(s2);
1314
          yield return new Edge<string, int>(s, s2, 0);
1315
          s2 = s + "R";
1316
          if (s2.Length < lmax)
1317
            q.Add(s2);
1318
          yield return new Edge<string, int>(s, s2, 0);
1319
        }
1320
      }
1321
    }
1322

    
1323
    /// <summary>
1324
    /// Create edges of a graph correspondingto a "wheel" shape: the ecnter and equidistant 
1325
    /// points around the perimeter. The edgedata and edge weights are the euclidean distances.
1326
    /// </summary>
1327
    /// <param name="complete">True means the graph will be complete, false that the graph
1328
    /// will have edges for the spokes and between neighboring perimeter vetices.</param>
1329
    /// <param name="n">The number of perimeter vertices, must be at least 3.</param>
1330
    /// <returns>An enumerable with the edges</returns>
1331
    static SCG.IEnumerable<Edge<string, double>> Wheel(bool complete, int n)
1332
    {
1333
      if (n < 3)
1334
        throw new ArgumentOutOfRangeException("n must be at least 3");
1335
      string center = "C";
1336
      string[] perimeter = new string[n];
1337
      for (int i = 0; i < n; i++)
1338
      {
1339
        perimeter[i] = "P" + i;
1340
        yield return new Edge<string, double>(perimeter[i], center, 1);
1341
      }
1342
      if (complete)
1343
        for (int i = 0; i < n - 1; i++)
1344
          for (int j = i + 1; j < n; j++)
1345
            yield return new Edge<string, double>(perimeter[i], perimeter[j], 2 * Math.Sin((j - i) * Math.PI / n));
1346
      else
1347
      {
1348
        for (int i = 0; i < n - 1; i++)
1349
          yield return new Edge<string, double>(perimeter[i], perimeter[i + 1], 2 * Math.Sin(Math.PI / n));
1350
        yield return new Edge<string, double>(perimeter[n - 1], perimeter[0], 2 * Math.Sin(Math.PI / n));
1351
      }
1352
    }
1353

    
1354

    
1355
    /// <summary>
1356
    /// []
1357
    /// </summary>
1358
    [ExampleDescription("Basic BFS and DFS using TraverseVertices method")]
1359
    static void test1()
1360
    {
1361
      IGraph<int, int, int> g = new HashGraph<int, int, int>(new CountWeight<int>(), Grid(3));
1362
      Console.WriteLine("Edge count: {0}", g.Edges().Count);
1363
      Console.WriteLine("BFS:");
1364
      g.TraverseVertices(true, 1001, delegate(Edge<int, int> e) { Console.WriteLine(e); });
1365
      Console.WriteLine("DFS:");
1366
      g.TraverseVertices(false, 1001, delegate(Edge<int, int> e) { Console.WriteLine(e); });
1367
    }
1368

    
1369
    /// <summary>
1370
    /// 
1371
    /// </summary>
1372
    [ExampleDescription("Component methods")]
1373
    static void testCOMP()
1374
    {
1375
      IGraph<string, int, int> g = new HashGraph<string, int, int>(new CountWeight<int>(), Forest(2, 2));
1376
      Console.WriteLine("Forest has: Vertices: {0}, Edges: {1}, Components: {2}", g.VertexCount, g.EdgeCount, g.ComponentCount);
1377
      //g.Print(Console.Out);
1378
      foreach (KeyValuePair<string, IGraph<string, int, int>> comp in g.Components())
1379
      {
1380
        Console.WriteLine("Component of {0}:", comp.Key);
1381
        comp.Value.Print(Console.Out);
1382
      }
1383
    }
1384

    
1385
    //TODO: remove?
1386
    static void test3()
1387
    {
1388
      HashGraph<int, int, int> g = new HashGraph<int, int, int>(new CountWeight<int>(), Grid(5));
1389
      g.Print(Console.Out);
1390
      //EdgeWeight<int, IntWeight> weight = delegate(int i) { return i; };
1391
      Console.WriteLine("========= PFS accum =========");
1392
      g.PriorityFirstTraverse(
1393
          true,
1394
          2002,
1395
          delegate(Edge<int, int> e, int d) { Console.WriteLine("Edge: {0}, at distance {1}", e, d); return true; });
1396
      Console.WriteLine("========= PFS not accum =========");
1397
      g.PriorityFirstTraverse(
1398
          false,
1399
          2002,
1400
          delegate(Edge<int, int> e, int d) { Console.WriteLine("Edge: {0}, at distance {1}", e, d); return true; });
1401
      Console.WriteLine("========= MST =========");
1402
      int root;
1403
      g.MinimumSpanningTree(out root).Print(Console.Out);
1404
      Console.WriteLine("========= SP =========");
1405
      foreach (Edge<int, int> edge in g.ShortestPath(1001, 5005))
1406
        Console.WriteLine(edge);
1407
    }
1408

    
1409
    static void test4()
1410
    {
1411
      IGraph<string, int, int> g = new HashGraph<string, int, int>(new IntWeight(), Snake(5));
1412
      Console.WriteLine("Edge count: {0}", g.Edges().Count);
1413
      Console.WriteLine("========= PFS =========");
1414
      g.PriorityFirstTraverse(false,
1415
          "U3",
1416
          delegate(Edge<string, int> e, int d) { Console.WriteLine("Edge: {0}, at distance {1}", e, d); return true; });
1417
      Console.WriteLine("========= MST =========");
1418
      string root;
1419
      IGraph<string, int, int> mst = g.MinimumSpanningTree(out root);
1420
      mst.Print(Console.Out);
1421
      Console.WriteLine("DFS:");
1422
      mst.TraverseVertices(false, root, delegate(Edge<string, int> e) { Console.WriteLine(e); });
1423
      Console.WriteLine("ATSP:");
1424
      int first = 0;
1425
      foreach (string s in g.ApproximateTSP())
1426
      {
1427
        Console.Write((first++ == 0 ? "" : " -> ") + s);
1428
      }
1429
    }
1430

    
1431
    /// <summary>
1432
    /// This example examines the two variants of a priority-first search:
1433
    ///  with accumulated weights, leading to shortest paths from start;
1434
    ///  with non-acumulated weights, leading to a minimum spanning tree.
1435
    /// </summary>
1436
    [ExampleDescription("Priority-first-search with and without accumulated weights")]
1437
    static void testPFS()
1438
    {
1439
      IGraph<string, double, double> g = new HashGraph<string, double, double>(new DoubleWeight(), Wheel(false, 10));
1440
      g.Print(Console.Out);
1441
      Console.WriteLine("========= PFS non-accumulated weights (-> MST) =========");
1442
      g.PriorityFirstTraverse(false,
1443
          "P0",
1444
          delegate(Edge<string, double> e, double d) { Console.WriteLine("Edge: {0}, at distance {1}", e, d); return true; });
1445
      Console.WriteLine("========= PFS accumulated weights (-> Shortst paths from start) =========");
1446
      g.PriorityFirstTraverse(true,
1447
          "P0",
1448
          delegate(Edge<string, double> e, double d) { Console.WriteLine("Edge: {0}, at distance {1}", e, d); return true; });
1449
    }
1450

    
1451
    /// <summary>
1452
    /// 
1453
    /// 
1454
    /// (Refer to Vazirani, or do that where ApproximateTSP is implemented)
1455
    /// 
1456
    /// Note that the tour created is not optimal. [Describe why]
1457
    /// </summary>
1458
    [ExampleDescription("Approximate TSP")]
1459
    static void testTSP()
1460
    {
1461
      IGraph<string, double, double> g = new HashGraph<string, double, double>(new DoubleWeight(), Wheel(true, 10));
1462
      //g.Print(Console.Out);
1463
      Console.WriteLine("========= MST =========");
1464
      string root;
1465
      IGraph<string, double, double> mst = g.MinimumSpanningTree(out root);
1466
      mst.TraverseVertices(false,
1467
         root,
1468
         delegate(Edge<string, double> e) { Console.WriteLine("Edge: {0} -> {1}", e.start, e.end); });
1469
      Console.WriteLine("========= Approximate TSP =========");
1470
      int first = 0;
1471
      foreach (string s in g.ApproximateTSP())
1472
      {
1473
        Console.Write((first++ == 0 ? "" : " -> ") + s);
1474
      }
1475
    }
1476

    
1477
    /// <summary>
1478
    /// 
1479
    /// 
1480
    /// (Refer to Vazirani, or do that where ApproximateTSP is implemented)
1481
    /// 
1482
    /// Note that the tour created is not optimal. [Describe why]
1483
    /// </summary>
1484
    [ExampleDescription("Approximate TSP2")]
1485
    static void testTSP2()
1486
    {
1487
      HashGraph<string, double, double> g = new HashGraph<string, double, double>(new DoubleWeight(), Wheel(true, 20));
1488

    
1489
      foreach (string s in g.ApproximateTSP2())
1490
        Console.WriteLine("# " + s);
1491
      //g.Print(Console.Out);
1492
      /*
1493
        Console.WriteLine("========= MST =========");
1494
        string root;
1495
        IGraph<string, double, double> mst = g.MinimumSpanningTree(out root);
1496
        mst.TraverseVertices(false,
1497
           root,
1498
           delegate(Edge<string, double> e) { Console.WriteLine("Edge: {0} -> {1}", e.start, e.end); });
1499
        ArrayList<string> oddvertices = new ArrayList<string>();
1500
        foreach (string v in mst.Vertices())
1501
            if (mst.Adjacent(v).Count % 2 != 0)
1502
                oddvertices.Add(v);
1503

    
1504
        Console.WriteLine("========= Matching of odd vertices of mst =========");
1505
        ICollectionValue<Edge<string, double>> matching = g.SubGraph(oddvertices).ApproximateMWPM();
1506

    
1507
        Console.WriteLine("========= Add matching to mst =========");
1508
        //We must split the edges of the matchin with fake temporary vertices
1509
        //(For a general vertex type, we would have to augment it to Pair<V,int> 
1510
        int fake = 0;
1511
        foreach (Edge<string, double> e in matching)
1512
        {
1513
            string fakevertex = "_" + (fake++);
1514
            mst.AddEdge(e.start, fakevertex, 0);
1515
            mst.AddEdge(fakevertex, e.end, e.edgedata);
1516
        }
1517
        //mst.Print(Console.Out);
1518

    
1519
        IList<string> tour = mst.EulerTour(), view = tour.View(1, tour.Count - 1);
1520

    
1521
        //Remove fake vertices
1522
         while (view.Count > 0)
1523
            if (view[0].StartsWith("_"))
1524
                view.RemoveFirst();
1525
            else
1526
                view.Slide(1, view.Count - 1);
1527

    
1528
        Console.WriteLine("========= Approximate TSP 2 =========");
1529
        //Short cut
1530
        view = tour.View(1, tour.Count - 1);
1531
        HashSet<string> seen = new HashSet<string>();
1532

    
1533
        while (view.Count > 0)
1534
        {
1535
            string s = view[0];
1536
            if (seen.FindOrAdd(ref s))
1537
                view.RemoveFirst();
1538
            else
1539
                view.Slide(1, view.Count - 1);
1540
        }
1541

    
1542
        foreach (string s in tour)
1543
            Console.WriteLine(". " + s);*/
1544
    }
1545

    
1546
    /// <summary>
1547
    /// 
1548
    /// </summary>
1549
    static void testEuler()
1550
    {
1551
      HashGraph<string, double, double> g = new HashGraph<string, double, double>(new DoubleWeight(), Wheel(true, 6));
1552
      foreach (string s in g.EulerTour())
1553
        Console.Write(s + " ");
1554
      Console.WriteLine();
1555
    }
1556

    
1557
    /// <summary>
1558
    /// An articulation point in a graph is a vertex, whose removal will 
1559
    /// disconnect the graph (or its component). This example uses the 
1560
    /// extended DepthFirstSearch method to compute articulation points
1561
    /// of a graph.
1562
    /// 
1563
    /// (Refer to Sedgewick. )
1564
    /// 
1565
    /// Each vertex is given an index in traversal order. 
1566
    /// For each vertex, we compute the least index reachable by going downwards
1567
    /// in the DFS tree and then following a single non-dfs edge. 
1568
    /// 
1569
    /// Since we cannot store the DFS indices in the vertices without changing the 
1570
    /// (assumed given) vertex type, V, we remember the indices in a V-&gt;int 
1571
    /// hash dictionary, index. The "least reachable" values are then stored in an 
1572
    /// array keyed by the index.
1573
    /// 
1574
    /// The root of the search is an articulation point if it has more than one
1575
    /// outgoing DFS edges. Other articulation points are non-root vertices, va,
1576
    /// with an outgoing DFS edge, where the the least reachable index of the other 
1577
    /// vertex is greater or equal to the index of va. 
1578
    /// </summary>
1579
    [ExampleDescription("Using the advanced DFS to compute articulation points")]
1580
    static void testDFS()
1581
    {
1582
      HashGraph<string, int, int> g = new HashGraph<string, int, int>(new IntWeight());
1583
      g.AddEdge("A", "B", 0);
1584
      g.AddEdge("A", "E", 0);
1585
      g.AddEdge("B", "E", 0);
1586
      g.AddEdge("B", "C", 0);
1587
      g.AddEdge("B", "H", 0);
1588
      g.AddEdge("H", "I", 0);
1589
      g.AddEdge("B", "D", 0);
1590
      g.AddEdge("C", "D", 0);
1591
      g.AddEdge("C", "F", 0);
1592
      g.AddEdge("C", "G", 0);
1593
      g.AddEdge("F", "G", 0);
1594

    
1595
      HashDictionary<string, int> index = new HashDictionary<string, int>();
1596
      int[] leastIndexReachableFrom = new int[g.VertexCount];
1597
      int nextindex = 0;
1598
      int outgoingFromRoot = 0;
1599
      Action<string> beforevertex = delegate(string v)
1600
      {
1601
        int i = (index[v] = nextindex++);
1602
        leastIndexReachableFrom[i] = i;
1603
      };
1604
      Action<string> aftervertex = delegate(string v)
1605
      {
1606
        int i = index[v];
1607
        if (i == 0 && outgoingFromRoot > 1)
1608
          Console.WriteLine("Articulation point: {0} ({1}>1 outgoing DFS edges from start)",
1609
              v, outgoingFromRoot);
1610
      };
1611
      Action<Edge<string, int>> onfollow = delegate(Edge<string, int> e)
1612
      {
1613
      };
1614
      Action<Edge<string, int>> onfollowed = delegate(Edge<string, int> e)
1615
      {
1616
        int startind = index[e.start], endind = index[e.end];
1617
        if (startind == 0)
1618
          outgoingFromRoot++;
1619
        else
1620
        {
1621
          int leastIndexReachable = leastIndexReachableFrom[endind];
1622
          if (leastIndexReachable >= startind)
1623
            Console.WriteLine("Articulation point: {0} (least index reachable via {3} is {1} >= this index {2})",
1624
                e.start, leastIndexReachable, startind, e);
1625
          if (leastIndexReachableFrom[startind] > leastIndexReachable)
1626
            leastIndexReachableFrom[startind] = leastIndexReachable;
1627
        }
1628
      };
1629
      Action<Edge<string, int>> onnotfollowed = delegate(Edge<string, int> e)
1630
      {
1631
        int startind = index[e.start], endind = index[e.end];
1632
        if (leastIndexReachableFrom[startind] > endind)
1633
          leastIndexReachableFrom[startind] = endind;
1634
      };
1635

    
1636
      string root = "C";
1637
      g.DepthFirstSearch(root, beforevertex, aftervertex, onfollow, onfollowed, onnotfollowed);
1638
      Console.WriteLine("Edges:");
1639
      foreach (Edge<string, int> e in g.Edges())
1640
        Console.WriteLine("/ {0}", e);
1641
    }
1642

    
1643
    static void Main(String[] args)
1644
    {
1645
      if (args.Length != 1)
1646
      {
1647
        Console.WriteLine("Usage: Graph.exe testno");
1648
        System.Reflection.MethodInfo[] mis = typeof(Test).GetMethods(
1649
            System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
1650
        foreach (System.Reflection.MethodInfo mi in mis)
1651
        {
1652
          if (mi.GetParameters().Length == 0 && mi.ReturnType == typeof(void) && mi.Name.StartsWith("test"))
1653
          {
1654
            object[] attrs = mi.GetCustomAttributes(typeof(ExampleDescriptionAttribute), false);
1655
            Console.WriteLine(" {0} : {1}", mi.Name.Substring(4), attrs.Length > 0 ? attrs[0] : "");
1656
          }
1657
        }
1658
      }
1659
      else
1660
      {
1661
        string testMethodName = String.Format("test{0}", args[0]);
1662

    
1663
        System.Reflection.MethodInfo mi = typeof(Test).GetMethod(testMethodName,
1664
            System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
1665

    
1666
        if (mi == null)
1667
          Console.WriteLine("No such testmethod, {0}", testMethodName);
1668
        else
1669
        {
1670
          object[] attrs = mi.GetCustomAttributes(typeof(ExampleDescriptionAttribute), false);
1671
          Console.WriteLine("============================== {0}() ==================================", testMethodName);
1672
          Console.WriteLine("Description: {0}", attrs.Length > 0 ? attrs[0] : "None");
1673
          Console.WriteLine("===========================================================================");
1674
          mi.Invoke(null, null);
1675
        }
1676
      }
1677
    }
1678
  }
1679
}