using System; using System.Text; using System.Collections.Generic; namespace Eppstein { /// /// Contains a simple vertex with label /// public class Vertex { /// /// Vertex label /// private string Label; /// /// Reference for a user object, for future use /// public object Object = null; #region Calculated fields /// /// Points to edge in shortest path tree /// public Edge EdgeToPath = null; /// /// Distance to endpoint in shortest path calculation /// public int Distance = int.MinValue; /// /// Collection of out edges not part of shortest path /// public List RelatedEdges = new List(); #endregion #region Properties /// /// Next vertex in shortest path /// public Vertex Next { get { return EdgeToPath == null ? null : EdgeToPath.Head; } } #endregion /// /// Public constructor /// /// Label of new vertex public Vertex(string _label) { Label = _label; } #region Overrided functions of Object class /// /// Converts this object into a string where required /// /// Vertex label public override string ToString() { return Label; } /// /// Allows to compare a vertex with another one by label, or with a string containin label /// /// Second object to compare with /// True if considered to be equal, false if not public override bool Equals(object _obj) { if (_obj == null) return false; if (_obj.GetType() == typeof(Vertex)) return (string.Compare(this.Label, ((Vertex)_obj).Label, StringComparison.InvariantCultureIgnoreCase) == 0); if (_obj.GetType() == typeof(string)) return (string.Compare(this.Label, (string)_obj, StringComparison.InvariantCultureIgnoreCase) == 0); return false; } /// /// Returns a hash for this object, it uses label's hash /// /// Hash calculated for this object public override int GetHashCode() { return Label.GetHashCode(); } #endregion } /// /// Contains a directional edge /// public class Edge { /// /// Index of tail vertex /// public readonly Vertex Tail; /// /// Index of head vertex /// public readonly Vertex Head; /// /// Weight of edge /// public int Weight; /// /// Group label of edge /// public readonly string Group; #region Properties /// /// Returns the sidetrack delta (deviation from shortest path) /// Only is valid when shortest path tree has been calculated /// public int Delta { get { return this.Weight + this.Head.Distance - this.Tail.Distance; } } #endregion /// /// Constructor, generates a valid Edge /// /// Vertex object of tail endpoint /// Vertex object of head endpoint /// Weight of edge /// Label of group where edge belongs to /// Edge is directional, goes from tail to head public Edge(Vertex _tail, Vertex _head, int _weight, string _group) { Tail = _tail; Head = _head; Weight = _weight; Group = _group; } /// /// Tells if the edge is a possible sidetrack of specified vertex /// /// Vertex to evaluate /// True if edge is sidetrack of vertex, false if not public bool IsSidetrackOf(Vertex _v) { return (this.Tail == _v && this != _v.EdgeToPath && this.Weight >= 0); } /// /// Converts this object into a string where required /// /// Tail and head labels, and weight inside parenthesis public override string ToString() { return string.Concat(this.Tail, "--" + this.Weight + "-->", this.Head); } } /// /// Contains a path composed by a edges collection /// public class Path : List { #region Properties /// /// Returns false if path is empty, true if not /// public bool IsValid { get { return (this.Count > 0); } } /// /// Returns string with comma-separated list containing all vertices in a path /// public string VertexNames { get { if (!IsValid) return "(empty)"; StringBuilder builder = new StringBuilder(this[0].Tail.ToString()); foreach (Edge e in this) { builder.Append("," + e.Head); } return builder.ToString(); } } /// /// Returns sum of all weights of edges in the path /// public int Weight { get { int total = 0; foreach (Edge e in this) total += e.Weight; return total; } } /// /// Returns sum of all deltas of edges in the path /// public int DeltaWeight { get { int total = 0; foreach (Edge e in this) total += e.Delta; return total; } } #endregion /// /// Returns path's decriptive string /// /// List of delta for path public override string ToString() { if (!IsValid) return "(empty)"; StringBuilder builder = new StringBuilder(); foreach (Edge _e in this) { builder.Append(_e.Delta); builder.Append(','); } if (builder.Length > 0) builder.Remove(builder.Length - 1, 1); return builder.ToString(); } } }