Example #1
0
        public async Task <UpdateResult> Recompile(Project gameProject, LoggerResult logger)
        {
            var result = new UpdateResult(logger);

            if (solution == null)
            {
                solution = gameProject.Solution;
            }

            // Detect new groups
            var gameProjectCompilation = await gameProject.GetCompilationAsync();

            // Generate source dependency graph
            var sourceDependencyGraph = new SourceGroup();

            // Make sure all vertices are added
            foreach (var syntaxTree in gameProjectCompilation.SyntaxTrees)
            {
                sourceDependencyGraph.AddVertex(syntaxTree);
            }

            foreach (var syntaxTree in gameProjectCompilation.SyntaxTrees)
            {
                var syntaxRoot    = syntaxTree.GetRoot();
                var semanticModel = gameProjectCompilation.GetSemanticModel(syntaxTree);

                var dependencies = new SourceDependencySyntaxVisitor(new HashSet <SyntaxTree>(gameProjectCompilation.SyntaxTrees), semanticModel).DefaultVisit(syntaxRoot);

                foreach (var dependency in dependencies)
                {
                    sourceDependencyGraph.AddEdge(new SEdge <SyntaxTree>(syntaxTree, dependency));
                }
            }

            // Generate strongly connected components for sources (group of sources that needs to be compiled together, and their dependencies)
            var stronglyConnected     = sourceDependencyGraph.CondensateStronglyConnected <SyntaxTree, SEdge <SyntaxTree>, SourceGroup>();
            var sortedConnectedGroups = stronglyConnected.TopologicalSort().ToArray();
            var connectedGroups       = ImmutableHashSet.Create(SourceGroupComparer.Default, sortedConnectedGroups);

            // Merge changes since previous time
            // 1. Tag obsolete groups (everything that don't match, and their dependencies)
            var groupsToUnload = new HashSet <SourceGroup>(SourceGroupComparer.Default);

            foreach (var sourceGroup in previousSortedConnectedGroups.Reverse())
            {
                // Does this group needs reload?
                SourceGroup newSourceGroup;
                if (connectedGroups.TryGetValue(sourceGroup, out newSourceGroup))
                {
                    // Transfer project, as it can be reused
                    newSourceGroup.Project  = sourceGroup.Project;
                    newSourceGroup.PE       = sourceGroup.PE;
                    newSourceGroup.PDB      = sourceGroup.PDB;
                    newSourceGroup.Assembly = sourceGroup.Assembly;
                }
                else
                {
                    groupsToUnload.Add(sourceGroup);
                }

                // Mark dependencies
                if (groupsToUnload.Contains(sourceGroup))
                {
                    foreach (var test in previousStronglyConnected.InEdges(sourceGroup))
                    {
                        groupsToUnload.Add(test.Source);
                    }
                }
            }

            // Generate common InternalsVisibleTo attributes
            // TODO: Find more graceful solution
            var internalsVisibleToBuilder = new StringBuilder();

            internalsVisibleToBuilder.Append("using System.Runtime.CompilerServices;");

            for (int i = 0; i < 1000; i++)
            {
                internalsVisibleToBuilder.AppendFormat(@"[assembly: InternalsVisibleTo(""{0}.Part{1}"")]", gameProject.AssemblyName, i);
            }

            var internalsVisibleToSource = CSharpSyntaxTree.ParseText(internalsVisibleToBuilder.ToString(), null, "", Encoding.UTF8).GetText();

            // 2. Compile assemblies
            foreach (var sourceGroup in sortedConnectedGroups.Reverse())
            {
                // Check if it's either a new group, or one that has been unloaded
                if (!previousConnectedGroups.Contains(sourceGroup) || groupsToUnload.Contains(sourceGroup))
                {
                    var assemblyName = gameProject.AssemblyName + ".Part" + assemblyCounter++;

                    // Create a project out of the source group
                    var project = solution.AddProject(assemblyName, assemblyName, LanguageNames.CSharp)
                                  .WithMetadataReferences(gameProject.MetadataReferences)
                                  .WithProjectReferences(gameProject.AllProjectReferences)
                                  .WithCompilationOptions(new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));

                    // Add sources
                    foreach (var syntaxTree in sourceGroup.Vertices)
                    {
                        project = project.AddDocument(syntaxTree.FilePath, syntaxTree.GetText()).Project;
                    }

                    // Add references to other sources
                    foreach (var dependencySourceGroup in stronglyConnected.OutEdges(sourceGroup))
                    {
                        project = project.AddProjectReference(new ProjectReference(dependencySourceGroup.Target.Project.Id));
                    }

                    // Make internals visible to other assembly parts
                    project = project.AddDocument("GeneratedInternalsVisibleTo", internalsVisibleToSource).Project;

                    sourceGroup.Project = project;
                    solution            = project.Solution;

                    var compilation = await project.GetCompilationAsync();

                    using (var peStream = new MemoryStream())
                        using (var pdbStream = new MemoryStream())
                        {
                            var emitResult = compilation.Emit(peStream, pdbStream);
                            result.Info($"Compiling assembly containing {sourceGroup}");

                            foreach (var diagnostic in emitResult.Diagnostics)
                            {
                                switch (diagnostic.Severity)
                                {
                                case DiagnosticSeverity.Error:
                                    result.Error(diagnostic.GetMessage());
                                    break;

                                case DiagnosticSeverity.Warning:
                                    result.Warning(diagnostic.GetMessage());
                                    break;

                                case DiagnosticSeverity.Info:
                                    result.Info(diagnostic.GetMessage());
                                    break;
                                }
                            }

                            if (!emitResult.Success)
                            {
                                result.Error($"Error compiling assembly containing {sourceGroup}");
                                break;
                            }

                            // Load csproj to evaluate assembly processor parameters
                            var msbuildProject = await Task.Run(() => VSProjectHelper.LoadProject(gameProject.FilePath));

                            if (msbuildProject.GetPropertyValue("StrideAssemblyProcessor") == "true")
                            {
                                var referenceBuild = await Task.Run(() => VSProjectHelper.CompileProjectAssemblyAsync(null, gameProject.FilePath, result, "ResolveReferences", flags: Microsoft.Build.Execution.BuildRequestDataFlags.ProvideProjectStateAfterBuild));

                                if (referenceBuild == null)
                                {
                                    result.Error("Could not properly run ResolveAssemblyReferences");
                                    break;
                                }
                                var referenceBuildResult = await referenceBuild.BuildTask;
                                if (referenceBuild.IsCanceled || result.HasErrors)
                                {
                                    break;
                                }

                                var assemblyProcessorParameters = "--parameter-key --auto-module-initializer --serialization";
                                var assemblyProcessorApp        = AssemblyProcessorProgram.CreateAssemblyProcessorApp(SplitCommandLine(assemblyProcessorParameters).ToArray(), new LoggerAssemblyProcessorWrapper(result));

                                foreach (var referencePath in referenceBuildResult.ProjectStateAfterBuild.Items.Where(x => x.ItemType == "ReferencePath"))
                                {
                                    assemblyProcessorApp.References.Add(referencePath.EvaluatedInclude);
                                    if (referencePath.EvaluatedInclude.EndsWith("Stride.SpriteStudio.Runtime.dll")) //todo hard-coded! needs to go when plug in system is in
                                    {
                                        assemblyProcessorApp.ReferencesToAdd.Add(referencePath.EvaluatedInclude);
                                    }
                                    else if (referencePath.EvaluatedInclude.EndsWith("Stride.Physics.dll")) //todo hard-coded! needs to go when plug in system is in
                                    {
                                        assemblyProcessorApp.ReferencesToAdd.Add(referencePath.EvaluatedInclude);
                                    }
                                    else if (referencePath.EvaluatedInclude.EndsWith("Stride.Particles.dll")) //todo hard-coded! needs to go when plug in system is in
                                    {
                                        assemblyProcessorApp.ReferencesToAdd.Add(referencePath.EvaluatedInclude);
                                    }
                                    else if (referencePath.EvaluatedInclude.EndsWith("Stride.Native.dll")) //todo hard-coded! needs to go when plug in system is in
                                    {
                                        assemblyProcessorApp.ReferencesToAdd.Add(referencePath.EvaluatedInclude);
                                    }
                                    else if (referencePath.EvaluatedInclude.EndsWith("Stride.UI.dll")) //todo hard-coded! needs to go when plug in system is in
                                    {
                                        assemblyProcessorApp.ReferencesToAdd.Add(referencePath.EvaluatedInclude);
                                    }
                                    else if (referencePath.EvaluatedInclude.EndsWith("Stride.Video.dll")) //todo hard-coded! needs to go when plug in system is in
                                    {
                                        assemblyProcessorApp.ReferencesToAdd.Add(referencePath.EvaluatedInclude);
                                    }
                                }

                                var assemblyResolver = assemblyProcessorApp.CreateAssemblyResolver();

                                // Add dependencies to assembly resolver
                                var recursiveDependencies = stronglyConnected.OutEdges(sourceGroup).SelectDeep(edge => stronglyConnected.OutEdges(edge.Target));
                                foreach (var dependencySourceGroup in recursiveDependencies)
                                {
                                    assemblyResolver.Register(dependencySourceGroup.Target.Assembly, dependencySourceGroup.Target.PE);
                                    assemblyProcessorApp.MemoryReferences.Add(dependencySourceGroup.Target.Assembly);
                                }

                                // Rewind streams
                                peStream.Position  = 0;
                                pdbStream.Position = 0;

                                var assemblyDefinition = AssemblyDefinition.ReadAssembly(peStream,
                                                                                         new ReaderParameters {
                                    AssemblyResolver = assemblyResolver, ReadSymbols = true, SymbolStream = pdbStream
                                });

                                // Run assembly processor
                                bool readWriteSymbols = true;
                                bool modified;
                                assemblyProcessorApp.SerializationAssembly = true;
                                if (!assemblyProcessorApp.Run(ref assemblyDefinition, ref readWriteSymbols, out modified))
                                {
                                    result.Error("Error running assembly processor");
                                    break;
                                }

                                sourceGroup.Assembly = assemblyDefinition;

                                // Write to file for now, since Cecil does not use the SymbolStream
                                var peFileName  = Path.ChangeExtension(Path.GetTempFileName(), ".dll");
                                var pdbFileName = Path.ChangeExtension(peFileName, ".pdb");
                                assemblyDefinition.Write(peFileName, new WriterParameters {
                                    WriteSymbols = true
                                });

                                sourceGroup.PE  = File.ReadAllBytes(peFileName);
                                sourceGroup.PDB = File.ReadAllBytes(pdbFileName);

                                File.Delete(peFileName);
                                File.Delete(pdbFileName);
                            }
                            else
                            {
                                sourceGroup.PE  = peStream.ToArray();
                                sourceGroup.PDB = pdbStream.ToArray();
                            }
                        }
                }
            }

            // We register unloading/loading only if everything succeeded
            if (!result.HasErrors)
            {
                // 3. Register old assemblies to unload
                foreach (var sourceGroup in previousSortedConnectedGroups)
                {
                    if (groupsToUnload.Contains(sourceGroup))
                    {
                        sourceGroup.Project  = null;
                        sourceGroup.Assembly = null;
                        result.UnloadedProjects.Add(sourceGroup);
                    }
                }

                // 4. Register new assemblies to load
                foreach (var sourceGroup in sortedConnectedGroups.Reverse())
                {
                    // Check if it's either a new group, or one that has been unloaded
                    if (!previousConnectedGroups.Contains(sourceGroup) || groupsToUnload.Contains(sourceGroup))
                    {
                        result.LoadedProjects.Add(sourceGroup);
                    }
                }

                // Set as new state
                previousSortedConnectedGroups = sortedConnectedGroups;
                previousStronglyConnected     = stronglyConnected;
                previousConnectedGroups       = connectedGroups;
            }

            return(result);
        }
        private static void RunStronglyConnectedCondensationAndCheck <TVertex, TEdge>(
            [NotNull] IVertexAndEdgeListGraph <TVertex, TEdge> graph)
            where TEdge : IEdge <TVertex>
        {
            IMutableBidirectionalGraph <AdjacencyGraph <TVertex, TEdge>, CondensedEdge <TVertex, TEdge, AdjacencyGraph <TVertex, TEdge> > > condensedGraph =
                graph.CondensateStronglyConnected <TVertex, TEdge, AdjacencyGraph <TVertex, TEdge> >();

            Assert.IsNotNull(condensedGraph);
            CheckVertexCount(graph, condensedGraph);
            CheckEdgeCount(graph, condensedGraph);
            CheckComponentCount(graph, condensedGraph);
            CheckDAG(condensedGraph);
        }
        public void MultipleWeaklyConnectedComponents()
        {
            var edge12 = new Edge <int>(1, 2);
            var edge13 = new Edge <int>(1, 3);
            var edge23 = new Edge <int>(2, 3);
            var edge42 = new Edge <int>(4, 2);
            var edge43 = new Edge <int>(4, 3);

            var edge56 = new Edge <int>(5, 6);
            var edge57 = new Edge <int>(5, 7);
            var edge76 = new Edge <int>(7, 6);

            var edge89 = new Edge <int>(8, 9);

            var graph = new AdjacencyGraph <int, Edge <int> >();

            graph.AddVerticesAndEdgeRange(new[]
            {
                edge12, edge13, edge23, edge42, edge43,
                edge56, edge57, edge76, edge89
            });

            IMutableBidirectionalGraph <AdjacencyGraph <int, Edge <int> >, CondensedEdge <int, Edge <int>, AdjacencyGraph <int, Edge <int> > > > condensedGraph =
                graph.CondensateWeaklyConnected <int, Edge <int>, AdjacencyGraph <int, Edge <int> > >();

            Assert.IsNotNull(condensedGraph);
            Assert.AreEqual(3, condensedGraph.VertexCount);
            Assert.AreEqual(0, condensedGraph.EdgeCount);
            CollectionAssert.AreEquivalent(
                new[] { 1, 2, 3, 4 },
                condensedGraph.Vertices.ElementAt(0).Vertices);
            CollectionAssert.AreEquivalent(
                new[] { edge12, edge13, edge23, edge42, edge43 },
                condensedGraph.Vertices.ElementAt(0).Edges);

            CollectionAssert.AreEquivalent(
                new[] { 5, 6, 7 },
                condensedGraph.Vertices.ElementAt(1).Vertices);
            CollectionAssert.AreEquivalent(
                new[] { edge56, edge57, edge76 },
                condensedGraph.Vertices.ElementAt(1).Edges);

            CollectionAssert.AreEquivalent(
                new[] { 8, 9 },
                condensedGraph.Vertices.ElementAt(2).Vertices);
            CollectionAssert.AreEquivalent(
                new[] { edge89 },
                condensedGraph.Vertices.ElementAt(2).Edges);
        }
        protected override void InternalCompute()
        {
            // create condensated graph
            this.condensedGraph = new BidirectionalGraph <
                TGraph,
                CondensedEdge <TVertex, TEdge, TGraph>
                >(false);
            if (this.VisitedGraph.VertexCount == 0)
            {
                return;
            }

            // compute strongly connected components
            var components     = new Dictionary <TVertex, int>(this.VisitedGraph.VertexCount);
            int componentCount = ComputeComponentCount(components);

            var cancelManager = this.Services.CancelManager;

            if (cancelManager.IsCancelling)
            {
                return;
            }

            // create list vertices
            var condensatedVertices = new Dictionary <int, TGraph>(componentCount);

            for (int i = 0; i < componentCount; ++i)
            {
                TGraph v = new TGraph();
                condensatedVertices.Add(i, v);
                this.condensedGraph.AddVertex(v);
            }

            // addingvertices
            foreach (var v in this.VisitedGraph.Vertices)
            {
                condensatedVertices[components[v]].AddVertex(v);
            }
            if (cancelManager.IsCancelling)
            {
                return;
            }

            // condensated edges
            var condensatedEdges = new Dictionary <EdgeKey, CondensedEdge <TVertex, TEdge, TGraph> >(componentCount);

            // iterate over edges and condensate graph
            foreach (var edge in this.VisitedGraph.Edges)
            {
                // get component ids
                int sourceID = components[edge.Source];
                int targetID = components[edge.Target];

                // get vertices
                TGraph sources = condensatedVertices[sourceID];
                if (sourceID == targetID)
                {
                    sources.AddEdge(edge);
                    continue;
                }

                var targets = condensatedVertices[targetID];
                // at last add edge
                var edgeKey = new EdgeKey(sourceID, targetID);
                CondensedEdge <TVertex, TEdge, TGraph> condensatedEdge;
                if (!condensatedEdges.TryGetValue(edgeKey, out condensatedEdge))
                {
                    condensatedEdge = new CondensedEdge <TVertex, TEdge, TGraph>(sources, targets);
                    condensatedEdges.Add(edgeKey, condensatedEdge);
                    this.condensedGraph.AddEdge(condensatedEdge);
                }
                condensatedEdge.Edges.Add(edge);
            }
        }
 internal ClusteredTopologicalSortAlgorithm(IVertexAndEdgeListGraph <TVertex, TEdge> graph, TopologicalSortOrder sortOrder)
 {
     _unprocessedGraph = graph.CopyTo <TVertex, TEdge, BidirectionalGraph <TVertex, TEdge> >();
     _sortOrder        = sortOrder;
 }
        public GraphHideHelpers([NotNull] IMutableBidirectionalGraph <TVertex, TEdge> managedGraph)
        {
            Debug.Assert(managedGraph != null);

            _graph = managedGraph;
        }
Example #7
0
 public GraphHideHelper(IMutableBidirectionalGraph <TVertex, TEdge> managedGraph)
 {
     graph = managedGraph;
 }
Example #8
0
        public ILayoutAlgorithm <TVertex, TEdge, TGraph> CreateLayoutAlgorithm(LayoutAlgorithmTypeEnum newAlgorithmType, TGraph iGraph, IDictionary <TVertex, Point> positions = null, IDictionary <TVertex, Size> sizes = null, ILayoutParameters parameters = null)
        {
            if (iGraph == null)
            {
                return(null);
            }
            if (parameters == null)
            {
                parameters = CreateLayoutParameters(newAlgorithmType);
            }
            IMutableBidirectionalGraph <TVertex, TEdge> graph = iGraph.CopyToBidirectionalGraph();

            /*var dic = new Dictionary<TVertex, Point>();
             * if (Positions != null)
             * {
             *  dic = Positions.Where(a => a.Key.SkipProcessing == ProcessingOptionEnum.Freeze).ToDictionary(a=> a.Key, a=> a.Value);
             * }*/
            graph.RemoveEdgeIf(a => a.SkipProcessing == ProcessingOptionEnum.Exclude);
            graph.RemoveVertexIf(a => a.SkipProcessing == ProcessingOptionEnum.Exclude);

            switch (newAlgorithmType)
            {
            case LayoutAlgorithmTypeEnum.Tree:
                return(new SimpleTreeLayoutAlgorithm <TVertex, TEdge, TGraph>((TGraph)graph, positions, sizes, parameters as SimpleTreeLayoutParameters));

            case LayoutAlgorithmTypeEnum.SimpleRandom:
                return(new RandomLayoutAlgorithm <TVertex, TEdge, TGraph>((TGraph)graph, positions));

            case LayoutAlgorithmTypeEnum.Circular:
                return(new CircularLayoutAlgorithm <TVertex, TEdge, TGraph>((TGraph)graph, positions, sizes, parameters as CircularLayoutParameters));

            case LayoutAlgorithmTypeEnum.FR:
                return(new FRLayoutAlgorithm <TVertex, TEdge, TGraph>((TGraph)graph, positions, parameters as FRLayoutParametersBase));

            case LayoutAlgorithmTypeEnum.BoundedFR:
                return(new FRLayoutAlgorithm <TVertex, TEdge, TGraph>((TGraph)graph, positions, parameters as BoundedFRLayoutParameters));

            case LayoutAlgorithmTypeEnum.KK:
                return(new KKLayoutAlgorithm <TVertex, TEdge, TGraph>((TGraph)graph, positions, parameters as KKLayoutParameters));

            case LayoutAlgorithmTypeEnum.ISOM:
                return(new ISOMLayoutAlgorithm <TVertex, TEdge, TGraph>((TGraph)graph, positions, parameters as ISOMLayoutParameters));

            case LayoutAlgorithmTypeEnum.LinLog:
                return(new LinLogLayoutAlgorithm <TVertex, TEdge, TGraph>((TGraph)graph, positions, parameters as LinLogLayoutParameters));

            case LayoutAlgorithmTypeEnum.EfficientSugiyama:
                return(new EfficientSugiyamaLayoutAlgorithm <TVertex, TEdge, TGraph>((TGraph)graph, parameters as EfficientSugiyamaLayoutParameters, positions, sizes));

            case LayoutAlgorithmTypeEnum.Sugiyama:
                return(new SugiyamaLayoutAlgorithm <TVertex, TEdge, TGraph>((TGraph)graph, sizes, positions, parameters as SugiyamaLayoutParameters,
                                                                            e => (e is TypedEdge <TVertex>
                                                                                  ?(e as TypedEdge <TVertex>).Type
                                                                                  : EdgeTypes.Hierarchical)));

            case LayoutAlgorithmTypeEnum.CompoundFDP:
                return(new CompoundFDPLayoutAlgorithm <TVertex, TEdge, TGraph>((TGraph)graph, sizes, new Dictionary <TVertex, Thickness>(), new Dictionary <TVertex, CompoundVertexInnerLayoutType>(),
                                                                               positions, parameters as CompoundFDPLayoutParameters));

            /*case LayoutAlgorithmTypeEnum.BalloonTree:
             *  return new BalloonTreeLayoutAlgorithm<TVertex, TEdge, TGraph>(Graph, Positions, Sizes, parameters as BalloonTreeLayoutParameters, Graph.Vertices.FirstOrDefault());*/
            default:
                return(null);
            }
        }
Example #9
0
 public ExampleExternalLayoutAlgorithm(IMutableBidirectionalGraph <DataVertex, DataEdge> graph)
 {
     _graph = graph;
 }
Example #10
0
        public void MultipleStronglyConnectedComponents()
        {
            var edge12 = new Edge <int>(1, 2);
            var edge23 = new Edge <int>(2, 3);
            var edge24 = new Edge <int>(2, 4);
            var edge25 = new Edge <int>(2, 5);
            var edge31 = new Edge <int>(3, 1);
            var edge34 = new Edge <int>(3, 4);
            var edge46 = new Edge <int>(4, 6);
            var edge56 = new Edge <int>(5, 6);
            var edge57 = new Edge <int>(5, 7);
            var edge64 = new Edge <int>(6, 4);
            var edge75 = new Edge <int>(7, 5);
            var edge78 = new Edge <int>(7, 8);
            var edge86 = new Edge <int>(8, 6);
            var edge87 = new Edge <int>(8, 7);

            var graph = new AdjacencyGraph <int, Edge <int> >();

            graph.AddVerticesAndEdgeRange(new[]
            {
                edge12, edge23, edge24, edge25, edge31, edge34, edge46,
                edge56, edge57, edge64, edge75, edge78, edge86, edge87
            });
            graph.AddVertex(10);

            IMutableBidirectionalGraph <AdjacencyGraph <int, Edge <int> >, CondensedEdge <int, Edge <int>, AdjacencyGraph <int, Edge <int> > > > condensedGraph =
                graph.CondensateStronglyConnected <int, Edge <int>, AdjacencyGraph <int, Edge <int> > >();

            Assert.IsNotNull(condensedGraph);
            Assert.AreEqual(4, condensedGraph.VertexCount);
            Assert.AreEqual(3, condensedGraph.EdgeCount);

            // Condensed edge
            CollectionAssert.AreEquivalent(
                new[] { edge56, edge86 },
                condensedGraph.Edges.ElementAt(0).Edges);
            CollectionAssert.AreEquivalent(
                new[] { edge24, edge34 },
                condensedGraph.Edges.ElementAt(1).Edges);
            CollectionAssert.AreEquivalent(
                new[] { edge25 },
                condensedGraph.Edges.ElementAt(2).Edges);

            // Components
            CollectionAssert.AreEquivalent(
                new[] { 4, 6 },
                condensedGraph.Vertices.ElementAt(0).Vertices);
            CollectionAssert.AreEquivalent(
                new[] { edge46, edge64 },
                condensedGraph.Vertices.ElementAt(0).Edges);

            CollectionAssert.AreEquivalent(
                new[] { 5, 7, 8 },
                condensedGraph.Vertices.ElementAt(1).Vertices);
            CollectionAssert.AreEquivalent(
                new[] { edge57, edge75, edge78, edge87 },
                condensedGraph.Vertices.ElementAt(1).Edges);

            CollectionAssert.AreEquivalent(
                new[] { 1, 2, 3 },
                condensedGraph.Vertices.ElementAt(2).Vertices);
            CollectionAssert.AreEquivalent(
                new[] { edge12, edge23, edge31 },
                condensedGraph.Vertices.ElementAt(2).Edges);

            CollectionAssert.AreEquivalent(
                new[] { 10 },
                condensedGraph.Vertices.ElementAt(3).Vertices);
            CollectionAssert.IsEmpty(condensedGraph.Vertices.ElementAt(3).Edges);
        }
Example #11
0
        public void OneStronglyConnectedComponent()
        {
            var edge12 = new Edge <int>(1, 2);
            var edge23 = new Edge <int>(2, 3);
            var edge31 = new Edge <int>(3, 1);

            var graph = new AdjacencyGraph <int, Edge <int> >();

            graph.AddVerticesAndEdgeRange(new[]
            {
                edge12, edge23, edge31
            });

            IMutableBidirectionalGraph <AdjacencyGraph <int, Edge <int> >, CondensedEdge <int, Edge <int>, AdjacencyGraph <int, Edge <int> > > > condensedGraph =
                graph.CondensateStronglyConnected <int, Edge <int>, AdjacencyGraph <int, Edge <int> > >();

            Assert.IsNotNull(condensedGraph);
            Assert.AreEqual(1, condensedGraph.VertexCount);
            Assert.AreEqual(0, condensedGraph.EdgeCount);
            CollectionAssert.AreEquivalent(graph.Vertices, condensedGraph.Vertices.ElementAt(0).Vertices);
            CollectionAssert.AreEquivalent(graph.Edges, condensedGraph.Vertices.ElementAt(0).Edges);
        }