//************************************************************************* // Constructor: OverallMetrics() // /// <summary> /// Initializes a new instance of the <see cref="OverallMetrics" /> class. /// </summary> /// /// <param name="directedness"> /// The graph's directedness. /// </param> /// /// <param name="uniqueEdges"> /// The number of unique edges. /// </param> /// /// <param name="edgesWithDuplicates"> /// The number of edges that have duplicates. /// </param> /// /// <param name="selfLoops"> /// The number of self-loops. /// </param> /// /// <param name="vertices"> /// The number of vertices. /// </param> /// /// <param name="graphDensity"> /// The graph's density, or null if the graph density can't be calculated. /// </param> /// /// <param name="connectedComponents"> /// The number of connected components in the graph. /// </param> /// /// <param name="singleVertexConnectedComponents"> /// The number of connected components in the graph that have one vertex. /// </param> /// /// <param name="maximumConnectedComponentVertices"> /// The maximum number of vertices in a connected component. /// </param> /// /// <param name="maximumConnectedComponentEdges"> /// The maximum number of edges in a connected component. /// </param> /// /// <param name="maximumGeodesicDistance"> /// The maximum geodesic distance in the graph, or null if not available. /// </param> /// /// <param name="averageGeodesicDistance"> /// The average geodesic distance in the graph, or null if not available. /// </param> //************************************************************************* public OverallMetrics ( GraphDirectedness directedness, Int32 uniqueEdges, Int32 edgesWithDuplicates, Int32 selfLoops, Int32 vertices, Nullable <Double> graphDensity, Int32 connectedComponents, Int32 singleVertexConnectedComponents, Int32 maximumConnectedComponentVertices, Int32 maximumConnectedComponentEdges, Nullable <Int32> maximumGeodesicDistance, Nullable <Double> averageGeodesicDistance ) { m_eDirectedness = directedness; m_iUniqueEdges = uniqueEdges; m_iEdgesWithDuplicates = edgesWithDuplicates; m_iSelfLoops = selfLoops; m_iVertices = vertices; m_dGraphDensity = graphDensity; m_iConnectedComponents = connectedComponents; m_iSingleVertexConnectedComponents = singleVertexConnectedComponents; m_iMaximumConnectedComponentVertices = maximumConnectedComponentVertices; m_iMaximumConnectedComponentEdges = maximumConnectedComponentEdges; m_iMaximumGeodesicDistance = maximumGeodesicDistance; m_dAverageGeodesicDistance = averageGeodesicDistance; AssertValid(); }
CheckGraphDirectedness ( IGraph graph, Boolean loading ) { AssertValid(); GraphDirectedness eDirectedness = graph.Directedness; if (SupportsDirectedness(eDirectedness)) { return; } throw new IOException(String.Format( "The graph can't be {0} as the file type you've selected, because" + " the graph is {1} and the file type can't be used with {1}" + " graphs." , loading ? "loaded" : "saved", EnumUtil.SplitName(eDirectedness.ToString(), EnumSplitStyle.AllWordsStartLowerCase) )); }
TestIsParallelTo ( GraphDirectedness eDirectedness, Int32 iEdge1Vertex1, Int32 iEdge1Vertex2, Boolean bEdge1IsDirected, Int32 iEdge2Vertex1, Int32 iEdge2Vertex2, Boolean bEdge2IsDirected, Boolean bExpectedEdge1IsParallelToEdge2 ) { const Int32 Vertices = 100; CreateGraph(eDirectedness, Vertices); IVertex oEdge1Vertex1 = m_aoVertices[iEdge1Vertex1]; IVertex oEdge1Vertex2 = m_aoVertices[iEdge1Vertex2]; IVertex oEdge2Vertex1 = m_aoVertices[iEdge2Vertex1]; IVertex oEdge2Vertex2 = m_aoVertices[iEdge2Vertex2]; IEdge oEdge1 = CreateEdge(oEdge1Vertex1, oEdge1Vertex2, bEdge1IsDirected); IEdge oEdge2 = CreateEdge(oEdge2Vertex1, oEdge2Vertex2, bEdge2IsDirected); IEdgeCollection oEdgeCollection = m_oGraph.Edges; oEdgeCollection.Add(oEdge1); oEdgeCollection.Add(oEdge2); Boolean bActualEdge1IsParallelToEdge2 = oEdge1.IsParallelTo(oEdge2); Assert.AreEqual( bExpectedEdge1IsParallelToEdge2, bActualEdge1IsParallelToEdge2); Boolean bActualEdge2IsParallelToEdge1 = oEdge2.IsParallelTo(oEdge1); Assert.AreEqual( bExpectedEdge1IsParallelToEdge2, bActualEdge2IsParallelToEdge1); Boolean bActualEdge1IsAntiparallelToEdge2 = oEdge1.IsAntiparallelTo(oEdge2); Assert.AreEqual( !bExpectedEdge1IsParallelToEdge2, bActualEdge1IsAntiparallelToEdge2 ); Boolean bActualEdge2IsAntiparallelToEdge1 = oEdge2.IsAntiparallelTo(oEdge1); Assert.AreEqual( !bExpectedEdge1IsParallelToEdge2, bActualEdge2IsAntiparallelToEdge1 ); }
CreateGraph ( IVertex [] aoVertices, List <PajekEdgeData> oUndirectedEdgeData, List <PajekEdgeData> oDirectedEdgeData ) { Debug.Assert(oUndirectedEdgeData != null); Debug.Assert(oDirectedEdgeData != null); GraphDirectedness eDirectedness = GraphDirectedness.Undirected; Int32 iVertices = 0; Int32 iUndirectedEdges = oUndirectedEdgeData.Count; Int32 iDirectedEdges = oDirectedEdgeData.Count; if (iUndirectedEdges > 0 && iDirectedEdges > 0) { eDirectedness = GraphDirectedness.Mixed; } else if (iDirectedEdges > 0) { eDirectedness = GraphDirectedness.Directed; } IGraph oGraph = new Graph(eDirectedness); IVertexCollection oVertices = oGraph.Vertices; IEdgeCollection oEdges = oGraph.Edges; if (aoVertices != null) { // Populate the vertex collection. foreach (IVertex oVertex in aoVertices) { oVertices.Add(oVertex); } iVertices = aoVertices.Length; } // Populate the edges collection. foreach (PajekEdgeData oEdgeData in oUndirectedEdgeData) { AddEdgeToGraph(oEdgeData, oEdges, aoVertices, false); } foreach (PajekEdgeData oEdgeData in oDirectedEdgeData) { AddEdgeToGraph(oEdgeData, oEdges, aoVertices, true); } return(oGraph); }
CreateGraph ( GraphDirectedness eDirectedness, Int32 iVertices ) { Debug.Assert(iVertices >= 0); m_oGraph = new Graph(eDirectedness); m_aoVertices = TestGraphUtil.AddVertices(m_oGraph, iVertices); }
LoadGraphCore ( Stream stream ) { Debug.Assert(stream != null); AssertValid(); XmlDocument oXmlDocument = new XmlDocument(); oXmlDocument.Load(stream); XmlNamespaceManager oXmlNamespaceManager = new XmlNamespaceManager( oXmlDocument.NameTable); oXmlNamespaceManager.AddNamespace(GraphMLPrefix, GraphMLUri); XmlNode oGraphMLXmlNode = oXmlDocument.DocumentElement; XmlNode oGraphXmlNode = XmlUtil2.SelectRequiredSingleNode( oGraphMLXmlNode, GraphMLPrefix + ":graph", oXmlNamespaceManager); // Parse the vertex and edge attribute definitions. // // The key is the id attribute of a "key" XML node, and the value is // the corresponding GraphMLAttribute object. Dictionary <String, GraphMLAttribute> oGraphMLAttributeDictionary = ParseGraphMLAttributeDefinitions(oGraphMLXmlNode, oXmlNamespaceManager); GraphDirectedness eGraphDirectedness = GetGraphDirectedness(oGraphXmlNode); IGraph oGraph = new Graph(eGraphDirectedness); // The key is the id attribute of the "node" XML node, and the value is // the corresponding IVertex. Dictionary <String, IVertex> oVertexDictionary = ParseVertices(oGraph, oGraphXmlNode, oXmlNamespaceManager, oGraphMLAttributeDictionary); ParseEdges(oGraph, oGraphXmlNode, oXmlNamespaceManager, oVertexDictionary, oGraphMLAttributeDictionary); SaveGraphMLAttributeNames(oGraph, oGraphMLAttributeDictionary); return(oGraph); }
LoadGraph ( String filename, GraphDirectedness fileDirectedness ) { AssertValid(); // Save the directedness for use by LoadGraphCore(), which will get // called by base.LoadGraph(). m_eLoadedGraphDirectedness = fileDirectedness; return(base.LoadGraphFromFile(filename)); }
Graph ( GraphDirectedness directedness ) : base(m_oIDGenerator.GetNextID()) { const String MethodName = "Constructor"; this.ArgumentChecker.CheckArgumentIsDefined( MethodName, "directedness", directedness, typeof(GraphDirectedness)); m_eDirectedness = directedness; m_oVertexCollection = new VertexCollection(this); m_oEdgeCollection = new EdgeCollection(this); AssertValid(); }
public IsParallelToInfo ( GraphDirectedness eDirectedness, Int32 iEdge1Vertex1, Int32 iEdge1Vertex2, Boolean bEdge1IsDirected, Int32 iEdge2Vertex1, Int32 iEdge2Vertex2, Boolean bEdge2IsDirected, Boolean bExpectedEdge1IsParallelToEdge2 ) { Directedness = eDirectedness; Edge1Vertex1 = iEdge1Vertex1; Edge1Vertex2 = iEdge1Vertex2; Edge1IsDirected = bEdge1IsDirected; Edge2Vertex1 = iEdge2Vertex1; Edge2Vertex2 = iEdge2Vertex2; Edge2IsDirected = bEdge2IsDirected; ExpectedEdge1IsParallelToEdge2 = bExpectedEdge1IsParallelToEdge2; }
InitializeGraph ( GraphDirectedness eDirectedness ) { m_oGraph = new Graph(eDirectedness); m_oGraph.Edges.EdgeAdded += new EdgeEventHandler( this.EdgeCollection_EdgeAdded); m_bEdgeAdded = false; m_oAddedEdge = null; m_oGraph.Vertices.VertexAdded += new VertexEventHandler( this.VertexCollection_VertexAdded); m_bVertexAdded = false; m_oAddedVertex = null; }
SupportsDirectedness ( GraphDirectedness directedness ) { AssertValid(); const String MethodName = "SupportsDirectedness"; const String ArgumentName = "directedness"; this.ArgumentChecker.CheckArgumentIsDefined( MethodName, ArgumentName, directedness, typeof(GraphDirectedness) ); Boolean bSupportsDirected, bSupportsUndirected, bSupportsMixed; GetSupportedDirectedness( out bSupportsDirected, out bSupportsUndirected, out bSupportsMixed); switch (directedness) { case GraphDirectedness.Directed: return(bSupportsDirected); case GraphDirectedness.Undirected: return(bSupportsUndirected); case GraphDirectedness.Mixed: return(bSupportsMixed); default: Debug.Assert(false); return(false); } }
//************************************************************************* // Method: InitializeGraph() // /// <summary> /// Initializes m_oGraph and related member fields. /// </summary> /// /// <param name="eDirectedness"> /// Directedness of m_oGraph. /// </param> //************************************************************************* protected void InitializeGraph( GraphDirectedness eDirectedness ) { m_oGraph = new Graph(eDirectedness); Debug.Assert(m_oGraph.Edges is EdgeCollection); m_oEdgeCollection = m_oGraph.Edges; ( (EdgeCollection)m_oEdgeCollection ).EdgeAdded += new EdgeEventHandler(this.EdgeCollection_EdgeAdded); ( (EdgeCollection)m_oEdgeCollection ).EdgeRemoved += new EdgeEventHandler(this.EdgeCollection_EdgeRemoved); m_bEdgeAdded = false; m_oAddedEdge = null; m_bEdgeRemoved = false; m_oRemovedEdge = null; }
//************************************************************************* // Method: AddEdges() // /// <summary> /// Adds a specified number of vertices to m_oGraph using one of the Add() /// methods, then connects some of them with edges. /// </summary> /// /// <param name="iVerticesToAdd"> /// Number of vertices to add. /// </param> /// /// <param name="eDirectedness"> /// Directedness of the added edges. /// </param> /// /// <param name="eAddOverload"> /// Specifies which overload of Add() to call. /// </param> /// /// <param name="aoVertices"> /// Where the added vertices get stored. /// </param> /// /// <param name="aoEdges"> /// Where the added edges get stored. /// </param> /// /// <remarks> /// The first vertex is connected to every other vertex. Thus, the number /// of added edges is <paramref name="iVerticesToAdd" /> minus one. /// </remarks> //************************************************************************* protected void AddEdges( Int32 iVerticesToAdd, GraphDirectedness eDirectedness, AddOverload eAddOverload, out IVertex [] aoVertices, out IEdge [] aoEdges ) { Debug.Assert(iVerticesToAdd >= 0); aoVertices = AddVertices(iVerticesToAdd); aoEdges = new IEdge[ Math.Max(0, iVerticesToAdd - 1) ]; for (Int32 i = 1; i < iVerticesToAdd; i++) { Boolean bDirected = false; switch (eDirectedness) { case GraphDirectedness.Directed: bDirected = true; break; case GraphDirectedness.Undirected: bDirected = false; break; case GraphDirectedness.Mixed: // Make every other edge directed. bDirected = (i % 2 == 0); break; default: Debug.Assert(false); break; } m_bEdgeAdded = false; m_oAddedEdge = null; IVertex oVertex1 = aoVertices[0]; IVertex oVertex2 = aoVertices[i]; IEdge oEdge = null; switch (eAddOverload) { case AddOverload.IEdge: oEdge = new Edge(oVertex1, oVertex2, bDirected); m_oEdgeCollection.Add(oEdge); break; case AddOverload.IVertex: oEdge = m_oEdgeCollection.Add( oVertex1, oVertex2, bDirected); break; case AddOverload.IVertexUndirected: oEdge = m_oEdgeCollection.Add(oVertex1, oVertex2); break; default: Debug.Assert(false); break; } oEdge.Name = oEdge.ID.ToString(); aoEdges[i - 1] = oEdge; Assert.IsTrue(m_bEdgeAdded); Assert.AreEqual(oEdge, m_oAddedEdge); } Assert.AreEqual( Math.Max(0, iVerticesToAdd - 1), m_oEdgeCollection.Count); }
//************************************************************************* // Method: AddEdges() // /// <summary> /// Adds a specified number of vertices to m_oGraph using one of the Add() /// methods, then connects some of them with edges. /// </summary> /// /// <param name="iVerticesToAdd"> /// Number of vertices to add. /// </param> /// /// <param name="eDirectedness"> /// Directedness of the added edges. /// </param> /// /// <param name="eAddOverload"> /// Specifies which overload of Add() to call. /// </param> /// /// <returns> /// An array of the added edges. /// </returns> /// /// <remarks> /// The first vertex is connected to every other vertex. Thus, the number /// of added edges is <paramref name="iVerticesToAdd" /> minus one. /// </remarks> //************************************************************************* protected IEdge[] AddEdges( Int32 iVerticesToAdd, GraphDirectedness eDirectedness, AddOverload eAddOverload ) { Debug.Assert(iVerticesToAdd >= 0); IVertex [] aoVertices; IEdge[] aoEdges; AddEdges(iVerticesToAdd, eDirectedness, eAddOverload, out aoVertices, out aoEdges); return (aoEdges); }
SaveGraphCore ( IGraph graph, Stream stream ) { Debug.Assert(graph != null); Debug.Assert(stream != null); AssertValid(); // The Pajek format requires coordinates to be between 0 and 1.0. Get // a Matrix that will transform the vertex locations to this range. RectangleF oCurrentBoundingRectangle = LayoutUtil.GetGraphBoundingRectangle(graph); RectangleF oNewBoundingRectangle = new RectangleF(PointF.Empty, new SizeF(1.0F, 1.0F)); Matrix oRectangleTransformation = LayoutUtil.GetRectangleTransformation( oCurrentBoundingRectangle, oNewBoundingRectangle ); // Create a dictionary to keep track of vertices. The keys are vertex // IDs and the values are the one-based vertex numbers used by the // Pajek format. Dictionary <Int32, Int32> oVertexIDToNumber = new Dictionary <Int32, Int32>(); IVertexCollection oVertices = graph.Vertices; StreamWriter oStreamWriter = new StreamWriter(stream, StreamEncoding); // Add the *vertices section. oStreamWriter.WriteLine( "*vertices {0}" , oVertices.Count ); Int32 iVertexNumber = 1; foreach (IVertex oVertex in oVertices) { // Format: // // 1 "vertex 1 name" x y z // Transform the vertex location. PointF oTransformedLocation = LayoutUtil.TransformPointF( oVertex.Location, oRectangleTransformation); // Limit the range in case of rounding errors. Single fX = Math.Max(0F, oTransformedLocation.X); fX = Math.Min(1F, fX); Single fY = Math.Max(0F, oTransformedLocation.Y); fY = Math.Min(1F, fY); oStreamWriter.WriteLine( "{0} \"{1}\" {2:N6} {3:N6} 0" , iVertexNumber, oVertex.Name, fX, fY ); oVertexIDToNumber.Add(oVertex.ID, iVertexNumber); iVertexNumber++; } IEdgeCollection oEdges = graph.Edges; GraphDirectedness eDirectedness = graph.Directedness; Boolean bSectionNameWritten = false; if (eDirectedness != GraphDirectedness.Directed) { // If appropriate, add the *edges section, which specifies // undirected edges. foreach (IEdge oEdge in oEdges) { // The graph could be mixed. if (oEdge.IsDirected) { continue; } if (!bSectionNameWritten) { oStreamWriter.WriteLine("*edges"); bSectionNameWritten = true; } WriteEdge(oEdge, oVertexIDToNumber, oStreamWriter); } } bSectionNameWritten = false; if (eDirectedness != GraphDirectedness.Undirected) { // If appropriate, add the *arcs section, which specifies // directed edges. foreach (IEdge oEdge in oEdges) { // The graph could be mixed. if (!oEdge.IsDirected) { continue; } if (!bSectionNameWritten) { oStreamWriter.WriteLine("*arcs"); bSectionNameWritten = true; } WriteEdge(oEdge, oVertexIDToNumber, oStreamWriter); } } oStreamWriter.Flush(); }
//************************************************************************* // Constructor: Graph() // /// <summary> /// Initializes a new instance of the <see cref="Graph" /> class with /// specified directedness. /// </summary> /// /// <param name="directedness"> /// Specifies the type of edges that can be added to the graph. /// </param> //************************************************************************* public Graph( GraphDirectedness directedness ) : base(m_oIDGenerator.GetNextID()) { const String MethodName = "Constructor"; this.ArgumentChecker.CheckArgumentIsDefined( MethodName, "directedness", directedness, typeof(GraphDirectedness) ); m_eDirectedness = directedness; m_oVertexCollection = new VertexCollection(this); m_oEdgeCollection = new EdgeCollection(this); AssertValid(); }
ImportMatrixWorkbook ( String sourceWorkbookName, Boolean sourceWorkbookHasVertexNames, GraphDirectedness sourceWorkbookDirectedness, Boolean clearDestinationTablesFirst, Microsoft.Office.Interop.Excel.Workbook destinationNodeXLWorkbook ) { Debug.Assert(!String.IsNullOrEmpty(sourceWorkbookName)); Debug.Assert(destinationNodeXLWorkbook != null); AssertValid(); // Get the active worksheet of the source workbook. Application oApplication = destinationNodeXLWorkbook.Application; Worksheet oSourceWorksheet = GetActiveSourceWorksheet( oApplication, sourceWorkbookName); // Read or create the names of the vertices in the source workbook. String [] asVertexNames; Int32 iFirstEdgeWeightRowOneBased, iFirstEdgeWeightColumnOneBased; if (sourceWorkbookHasVertexNames) { asVertexNames = ReadVertexNames(oSourceWorksheet); iFirstEdgeWeightRowOneBased = iFirstEdgeWeightColumnOneBased = 2; } else { asVertexNames = CreateVertexNames(oSourceWorksheet); iFirstEdgeWeightRowOneBased = iFirstEdgeWeightColumnOneBased = 1; } Boolean bGraphIsDirected = false; switch (sourceWorkbookDirectedness) { case GraphDirectedness.Directed: bGraphIsDirected = true; break; case GraphDirectedness.Undirected: CheckSymmetryOfUndirectedMatrix(oSourceWorksheet, iFirstEdgeWeightRowOneBased, iFirstEdgeWeightColumnOneBased, asVertexNames.Length); break; default: Debug.Assert(false); break; } // Read the edge weights and write the results to the destination // workbook. LinkedList <String> oVertex1Names = new LinkedList <String>(); LinkedList <String> oVertex2Names = new LinkedList <String>(); LinkedList <Double> oEdgeWeights = new LinkedList <Double>(); ReadEdgeWeights(oSourceWorksheet, bGraphIsDirected, iFirstEdgeWeightRowOneBased, iFirstEdgeWeightColumnOneBased, asVertexNames, oVertex1Names, oVertex2Names, oEdgeWeights ); WriteToDestinationWorkbook(oVertex1Names, oVertex2Names, oEdgeWeights, clearDestinationTablesFirst, destinationNodeXLWorkbook); }
//************************************************************************* // Method: SupportsDirectedness() // /// <summary> /// Returns a flag indicating whether the graph adapter can be used with /// graphs of a specified <see cref="GraphDirectedness" />. /// </summary> /// /// <param name="directedness"> /// A <see cref="GraphDirectedness" /> value. /// </param> /// /// <returns> /// true if the graph adapter can be used with graphs of the specified /// directedness. /// </returns> //************************************************************************* public Boolean SupportsDirectedness( GraphDirectedness directedness ) { AssertValid(); const String MethodName = "SupportsDirectedness"; const String ArgumentName = "directedness"; this.ArgumentChecker.CheckArgumentIsDefined( MethodName, ArgumentName, directedness, typeof(GraphDirectedness) ); Boolean bSupportsDirected, bSupportsUndirected, bSupportsMixed; GetSupportedDirectedness( out bSupportsDirected, out bSupportsUndirected, out bSupportsMixed); switch (directedness) { case GraphDirectedness.Directed: return (bSupportsDirected); case GraphDirectedness.Undirected: return (bSupportsUndirected); case GraphDirectedness.Mixed: return (bSupportsMixed); default: Debug.Assert(false); return (false); } }
LoadGraph ( String filename, GraphDirectedness fileDirectedness ) { AssertValid(); // Save the directedness for use by LoadGraphCore(), which will get // called by base.LoadGraph(). m_eLoadedGraphDirectedness = fileDirectedness; return ( base.LoadGraphFromFile(filename) ); }
ImportMatrixWorkbook ( Microsoft.Office.Interop.Excel.Application application, String sourceWorkbookName, Boolean sourceWorkbookHasVertexNames, GraphDirectedness sourceWorkbookDirectedness ) { Debug.Assert(application != null); Debug.Assert(!String.IsNullOrEmpty(sourceWorkbookName)); AssertValid(); // Get the active worksheet of the source workbook. Worksheet oSourceWorksheet = GetActiveSourceWorksheet( application, sourceWorkbookName); // Read or create the names of the vertices in the source workbook. String [] asVertexNames; Int32 iFirstEdgeWeightRowOneBased, iFirstEdgeWeightColumnOneBased; if (sourceWorkbookHasVertexNames) { asVertexNames = ReadVertexNames(oSourceWorksheet); iFirstEdgeWeightRowOneBased = iFirstEdgeWeightColumnOneBased = 2; } else { asVertexNames = CreateVertexNames(oSourceWorksheet); iFirstEdgeWeightRowOneBased = iFirstEdgeWeightColumnOneBased = 1; } Int32 iVertices = asVertexNames.Length; switch (sourceWorkbookDirectedness) { case GraphDirectedness.Directed: break; case GraphDirectedness.Undirected: CheckSymmetryOfUndirectedMatrix(oSourceWorksheet, iFirstEdgeWeightRowOneBased, iFirstEdgeWeightColumnOneBased, iVertices); break; default: Debug.Assert(false); break; } // Create a graph and populate it with the vertices. IGraph oGraph = new Graph(sourceWorkbookDirectedness); IVertexCollection oVertices = oGraph.Vertices; IVertex[] aoOrderedVertices = new IVertex[iVertices]; for (Int32 i = 0; i < iVertices; i++) { IVertex oVertex = oVertices.Add(); oVertex.Name = asVertexNames[i]; aoOrderedVertices[i] = oVertex; } // Read the edges and import them into the graph. ReadEdges(oSourceWorksheet, iFirstEdgeWeightRowOneBased, iFirstEdgeWeightColumnOneBased, oGraph, aoOrderedVertices); return(oGraph); }
//************************************************************************* // Constructor: OverallMetrics() // /// <summary> /// Initializes a new instance of the <see cref="OverallMetrics" /> class. /// </summary> /// /// <param name="directedness"> /// The graph's directedness. /// </param> /// /// <param name="uniqueEdges"> /// The number of unique edges. /// </param> /// /// <param name="edgesWithDuplicates"> /// The number of edges that have duplicates. /// </param> /// /// <param name="selfLoops"> /// The number of self-loops. /// </param> /// /// <param name="vertices"> /// The number of vertices. /// </param> /// /// <param name="graphDensity"> /// The graph's density, or null if the graph density can't be calculated. /// </param> /// /// <param name="connectedComponents"> /// The number of connected components in the graph. /// </param> /// /// <param name="singleVertexConnectedComponents"> /// The number of connected components in the graph that have one vertex. /// </param> /// /// <param name="maximumConnectedComponentVertices"> /// The maximum number of vertices in a connected component. /// </param> /// /// <param name="maximumConnectedComponentEdges"> /// The maximum number of edges in a connected component. /// </param> /// /// <param name="maximumGeodesicDistance"> /// The maximum geodesic distance in the graph, or null if not available. /// </param> /// /// <param name="averageGeodesicDistance"> /// The average geodesic distance in the graph, or null if not available. /// </param> //************************************************************************* public OverallMetrics( GraphDirectedness directedness, Int32 uniqueEdges, Int32 edgesWithDuplicates, Int32 selfLoops, Int32 vertices, Nullable<Double> graphDensity, Int32 connectedComponents, Int32 singleVertexConnectedComponents, Int32 maximumConnectedComponentVertices, Int32 maximumConnectedComponentEdges, Nullable<Int32> maximumGeodesicDistance, Nullable<Double> averageGeodesicDistance ) { m_eDirectedness = directedness; m_iUniqueEdges = uniqueEdges; m_iEdgesWithDuplicates = edgesWithDuplicates; m_iSelfLoops = selfLoops; m_iVertices = vertices; m_dGraphDensity = graphDensity; m_iConnectedComponents = connectedComponents; m_iSingleVertexConnectedComponents = singleVertexConnectedComponents; m_iMaximumConnectedComponentVertices = maximumConnectedComponentVertices; m_iMaximumConnectedComponentEdges = maximumConnectedComponentEdges; m_iMaximumGeodesicDistance = maximumGeodesicDistance; m_dAverageGeodesicDistance = averageGeodesicDistance; AssertValid(); }
TestRandomGraph ( Int32 iVertices, Random oRandom ) { Debug.Assert(iVertices >= 0); Debug.Assert(oRandom != null); // Stores the edges actually added to the graph. List <IEdge> oActualEdges = new List <IEdge>(); // Create a graph with random directedness. GraphDirectedness eDirectedness = TestGraphUtil.AllGraphDirectedness[ oRandom.Next(TestGraphUtil.AllGraphDirectedness.Length)]; InitializeGraph(eDirectedness); // Add random vertices. IVertex [] aoVertices = TestGraphUtil.AddVertices(m_oGraph, iVertices); Assert.AreEqual(iVertices, m_oGraph.Vertices.Count); Assert.AreEqual(0, m_oGraph.Edges.Count); // Add random edges. Int32 iAttemptedEdges = oRandom.Next(iVertices); IEdgeCollection oEdgeCollection = m_oGraph.Edges; for (Int32 i = 0; i < iAttemptedEdges; i++) { Boolean bIsDirected = false; switch (eDirectedness) { case GraphDirectedness.Undirected: bIsDirected = false; break; case GraphDirectedness.Directed: bIsDirected = true; break; case GraphDirectedness.Mixed: bIsDirected = (oRandom.Next(2) % 2 == 0); break; default: Debug.Assert(false); break; } IVertex oVertex1 = aoVertices[oRandom.Next(iVertices)]; IVertex oVertex2 = aoVertices[oRandom.Next(iVertices)]; IEdge oEdge = oEdgeCollection.Add(oVertex1, oVertex2, bIsDirected); oActualEdges.Add(oEdge); } Assert.AreEqual(iVertices, m_oGraph.Vertices.Count); Assert.AreEqual(oActualEdges.Count, m_oGraph.Edges.Count); // Set random metadata. foreach (IVertex oVertex in m_oGraph.Vertices) { String sName = null; if (oRandom.Next(3) % 3 == 0) { MetadataUtil.SetRandomMetadata( oVertex, true, true, oVertex.ID); // Mark the vertex as having metadata. sName = MetadataMarker; } oVertex.Name = sName; } foreach (IEdge oEdge in m_oGraph.Edges) { String sName = null; if (oRandom.Next(4) % 4 == 0) { MetadataUtil.SetRandomMetadata(oEdge, true, true, oEdge.ID); sName = MetadataMarker; } oEdge.Name = sName; } MetadataUtil.SetRandomMetadata(m_oGraph, true, true, m_oGraph.ID); // Check the random metadata. CheckRandomMetadataOnRandomGraph(); // Remove random edges. Int32 iRemovedEdges = 0; if (oRandom.Next(2) % 2 == 0) { foreach (IEdge oEdge in oActualEdges) { if (oRandom.Next(5) % 5 == 0) { m_oGraph.Edges.Remove(oEdge); iRemovedEdges++; } } } Assert.AreEqual(iVertices, m_oGraph.Vertices.Count); Assert.AreEqual(oActualEdges.Count - iRemovedEdges, m_oGraph.Edges.Count); // Remove random vertices. Int32 iRemovedVertices = 0; if (oRandom.Next(2) % 2 == 0) { foreach (IVertex oVertex in aoVertices) { if (oRandom.Next(3) % 3 == 0) { m_oGraph.Vertices.Remove(oVertex); iRemovedVertices++; } } } Assert.AreEqual(iVertices - iRemovedVertices, m_oGraph.Vertices.Count); // Note: Can't test m_oGraph.Edges.Count here, because removing // vertices probably removed some edges as well. // Check the random metadata on the remaining objects. CheckRandomMetadataOnRandomGraph(); // Check all the vertices, including the ones that were removed. // First, store all the non-removed vertex IDs in a dictionary to avoid // having to repeatedly call Vertices.Contains(), which is slow. Dictionary <Int32, Byte> oContainedVertexIDs = new Dictionary <Int32, Byte>(); foreach (IVertex oVertex in m_oGraph.Vertices) { oContainedVertexIDs.Add(oVertex.ID, 0); } foreach (IVertex oVertex in aoVertices) { Boolean bContainedInGraph = oContainedVertexIDs.ContainsKey(oVertex.ID); Assert.AreEqual(bContainedInGraph, oVertex.ParentGraph != null); if (oVertex.Name == MetadataMarker) { MetadataUtil.CheckRandomMetadata( oVertex, true, true, oVertex.ID); } else { Assert.IsNull(oVertex.Tag); } } oContainedVertexIDs.Clear(); // Remove all edges. m_oGraph.Edges.Clear(); Assert.AreEqual(iVertices - iRemovedVertices, m_oGraph.Vertices.Count); Assert.AreEqual(0, m_oGraph.Edges.Count); // Remove all vertices. m_oGraph.Vertices.Clear(); Assert.AreEqual(0, m_oGraph.Vertices.Count); Assert.AreEqual(0, m_oGraph.Edges.Count); // Check all the vertices. foreach (IVertex oVertex in aoVertices) { Boolean bContainedInGraph = m_oGraph.Vertices.Contains(oVertex); Assert.IsFalse(bContainedInGraph); if (oVertex.Name == MetadataMarker) { MetadataUtil.CheckRandomMetadata( oVertex, true, true, oVertex.ID); } else { Assert.IsNull(oVertex.Tag); } } }
ImportMatrixWorkbook ( Microsoft.Office.Interop.Excel.Application application, String sourceWorkbookName, Boolean sourceWorkbookHasVertexNames, GraphDirectedness sourceWorkbookDirectedness ) { Debug.Assert(application != null); Debug.Assert( !String.IsNullOrEmpty(sourceWorkbookName) ); AssertValid(); // Get the active worksheet of the source workbook. Worksheet oSourceWorksheet = GetActiveSourceWorksheet( application, sourceWorkbookName); // Read or create the names of the vertices in the source workbook. String [] asVertexNames; Int32 iFirstEdgeWeightRowOneBased, iFirstEdgeWeightColumnOneBased; if (sourceWorkbookHasVertexNames) { asVertexNames = ReadVertexNames(oSourceWorksheet); iFirstEdgeWeightRowOneBased = iFirstEdgeWeightColumnOneBased = 2; } else { asVertexNames = CreateVertexNames(oSourceWorksheet); iFirstEdgeWeightRowOneBased = iFirstEdgeWeightColumnOneBased = 1; } Int32 iVertices = asVertexNames.Length; switch (sourceWorkbookDirectedness) { case GraphDirectedness.Directed: break; case GraphDirectedness.Undirected: CheckSymmetryOfUndirectedMatrix(oSourceWorksheet, iFirstEdgeWeightRowOneBased, iFirstEdgeWeightColumnOneBased, iVertices); break; default: Debug.Assert(false); break; } // Create a graph and populate it with the vertices. IGraph oGraph = new Graph(sourceWorkbookDirectedness); IVertexCollection oVertices = oGraph.Vertices; IVertex[] aoOrderedVertices = new IVertex[iVertices]; for (Int32 i = 0; i < iVertices; i++) { IVertex oVertex = oVertices.Add(); oVertex.Name = asVertexNames[i]; aoOrderedVertices[i] = oVertex; } // Read the edges and import them into the graph. ReadEdges(oSourceWorksheet, iFirstEdgeWeightRowOneBased, iFirstEdgeWeightColumnOneBased, oGraph, aoOrderedVertices); return (oGraph); }
//************************************************************************* // Method: ImportMatrixWorkbook() // /// <summary> /// Imports a graph from an open matrix workbook to the edge worksheet of a /// NodeXL workbook. /// </summary> /// /// <param name="sourceWorkbookName"> /// Workbook.Name of the open workbook that contains the matrix to import. /// </param> /// /// <param name="sourceWorkbookHasVertexNames"> /// true if the source workbook has vertex names in row 1 and column A, /// false if the source workbook has no vertex names and sequential vertex /// names should be assigned during importation. /// </param> /// /// <param name="sourceWorkbookDirectedness"> /// The directedness of the graph represented by the source workbook. /// </param> /// /// <param name="clearDestinationTablesFirst"> /// true if the NodeXL tables in <paramref /// name="destinationNodeXLWorkbook" /> should be cleared first. /// </param> /// /// <param name="destinationNodeXLWorkbook"> /// NodeXL workbook the graph will be imported to. /// </param> /// /// <remarks> /// The source workbook must specify a numerical edge weight for each pair /// of vertices. Empty edge weight cells are not allowed. /// /// <para> /// If the source workbook has vertex names, the names must be in row 1, /// starting in B1; and in column A, starting in A2. The edge weights must /// start in B2. /// </para> /// /// <para> /// If the source workbook does not have vertex names, the edge weights /// must start in A1. /// </para> /// /// <para> /// If the source workbook represents a directed graph, every cell in the /// matrix is read. If the source workbook represents an undirected graph, /// the matrix must be symmetric and only the cells in the matrix's /// diagonal and above are read. /// /// An edge weight on the diagonal, which represents a self-loop, is not /// treated in any special way. It's up to the user to decide which /// convention she wants to adopt regarding the meaning of self-loop edge /// weights. /// </para> /// /// </remarks> //************************************************************************* public void ImportMatrixWorkbook( String sourceWorkbookName, Boolean sourceWorkbookHasVertexNames, GraphDirectedness sourceWorkbookDirectedness, Boolean clearDestinationTablesFirst, Microsoft.Office.Interop.Excel.Workbook destinationNodeXLWorkbook ) { Debug.Assert( !String.IsNullOrEmpty(sourceWorkbookName) ); Debug.Assert(destinationNodeXLWorkbook != null); AssertValid(); // Get the active worksheet of the source workbook. Application oApplication = destinationNodeXLWorkbook.Application; Worksheet oSourceWorksheet = GetActiveSourceWorksheet( oApplication, sourceWorkbookName); // Read or create the names of the vertices in the source workbook. String [] asVertexNames; Int32 iFirstEdgeWeightRowOneBased, iFirstEdgeWeightColumnOneBased; if (sourceWorkbookHasVertexNames) { asVertexNames = ReadVertexNames(oSourceWorksheet); iFirstEdgeWeightRowOneBased = iFirstEdgeWeightColumnOneBased = 2; } else { asVertexNames = CreateVertexNames(oSourceWorksheet); iFirstEdgeWeightRowOneBased = iFirstEdgeWeightColumnOneBased = 1; } Boolean bGraphIsDirected = false; switch (sourceWorkbookDirectedness) { case GraphDirectedness.Directed: bGraphIsDirected = true; break; case GraphDirectedness.Undirected: CheckSymmetryOfUndirectedMatrix(oSourceWorksheet, iFirstEdgeWeightRowOneBased, iFirstEdgeWeightColumnOneBased, asVertexNames.Length); break; default: Debug.Assert(false); break; } // Read the edge weights and write the results to the destination // workbook. LinkedList<String> oVertex1Names = new LinkedList<String>(); LinkedList<String> oVertex2Names = new LinkedList<String>(); LinkedList <Double> oEdgeWeights = new LinkedList<Double>(); ReadEdgeWeights(oSourceWorksheet, bGraphIsDirected, iFirstEdgeWeightRowOneBased, iFirstEdgeWeightColumnOneBased, asVertexNames, oVertex1Names, oVertex2Names, oEdgeWeights ); WriteToDestinationWorkbook(oVertex1Names, oVertex2Names, oEdgeWeights, clearDestinationTablesFirst, destinationNodeXLWorkbook); }
LoadGraphCore ( Stream stream ) { Debug.Assert(stream != null); AssertValid(); XmlDocument oXmlDocument = new XmlDocument(); if (stream.Position > 0) { stream.Position = 0; } string fileName; //Code from: http://msdn.microsoft.com/en-us/library/system.io.stream.read%28v=vs.110%29.aspx byte[] buffer; { int length = (int)stream.Length; // get file length buffer = new byte[length]; // create buffer int count; // actual number of bytes read int sum = 0; // total number of bytes read // read until Read method returns 0 (end of the stream has been reached) while ((count = stream.Read(buffer, sum, length - sum)) > 0) { sum += count; // sum is a buffer offset for next reading } fileName = System.Text.Encoding.UTF8.GetString(buffer); fileName = fileName.Replace(System.Environment.NewLine, ""); } oXmlDocument.Load(fileName); XmlNamespaceManager oXmlNamespaceManager = new XmlNamespaceManager( oXmlDocument.NameTable); oXmlNamespaceManager.AddNamespace(GraphMLPrefix, GraphMLNamespaceUri); XmlNode oGraphMLXmlNode = oXmlDocument.DocumentElement; XmlNode oGraphXmlNode = XmlUtil2.SelectRequiredSingleNode( oGraphMLXmlNode, GraphMLPrefix + ":graph", oXmlNamespaceManager); // Parse the vertex and edge attribute definitions. // // The key is the id attribute of a "key" XML node, and the value is // the corresponding GraphMLAttribute object. Dictionary <String, GraphMLAttribute> oGraphMLAttributeDictionary = ParseGraphMLAttributeDefinitions(oGraphMLXmlNode, oXmlNamespaceManager); GraphDirectedness eGraphDirectedness = GetGraphDirectedness(oGraphXmlNode); IGraph oGraph = new Graph(eGraphDirectedness); // The key is the id attribute of the "node" XML node, and the value is // the corresponding IVertex. Dictionary <String, IVertex> oVertexDictionary = ParseVertices(oGraph, oGraphXmlNode, oXmlNamespaceManager, oGraphMLAttributeDictionary); ParseEdges(oGraph, oGraphXmlNode, oXmlNamespaceManager, oVertexDictionary, oGraphMLAttributeDictionary); ParseGraphAttribute(oGraph, oGraphXmlNode, "description", ReservedMetadataKeys.GraphDescription); ParseGraphAttribute(oGraph, oGraphXmlNode, "suggestedTitle", ReservedMetadataKeys.SuggestedTitle); ParseGraphAttribute(oGraph, oGraphXmlNode, "suggestedFileNameNoExtension", ReservedMetadataKeys.SuggestedFileNameNoExtension); SaveGraphMLAttributeNames(oGraph, oGraphMLAttributeDictionary); return(oGraph); }
//************************************************************************* // Method: CreateGraph() // /// <summary> /// Creates a graph of a specified directedness that is compatible with /// <see cref="PajekGraphAdapter" />. /// </summary> /// /// <param name="eDirectedness"> /// Directedness of the new graph. /// </param> /// /// <returns> /// A new compatible graph. /// </returns> //************************************************************************* protected IGraph CreateGraph( GraphDirectedness eDirectedness ) { IGraph oGraph = new Graph(eDirectedness); return (oGraph); }
//************************************************************************* // Constructor: UcinetGraphAdapter() // /// <summary> /// Initializes a new instance of the <see cref="UcinetGraphAdapter" /> /// class. /// </summary> //************************************************************************* public UcinetGraphAdapter() { m_eLoadedGraphDirectedness = GraphDirectedness.Undirected; AssertValid(); }