public void DirectedGraphSortsAcyclicVerticesTest() { var graph = new DirectedGraph<int>(new[] { 4, 2, 1, 5, 3 }); // Add non-cyclic edges graph.AddEdge(1, 2); graph.AddEdge(1, 5); graph.AddEdge(2, 3); graph.AddEdge(2, 4); graph.AddEdge(3, 4); graph.AddEdge(3, 5); graph.AddEdge(4, 5); graph.Sort().Should().BeInAscendingOrder("Expected vertices to be sorted"); }
static IReadOnlyDictionary<string, IReadOnlyList<Export<IStyleRule, StyleRuleMetadata>>> OrderAndMapRules( IReadOnlyList<Export<IStyleRule, StyleRuleMetadata>> rules) { var languageRuleMap = new Dictionary<string, IReadOnlyList<Export<IStyleRule, StyleRuleMetadata>>>(); ILookup<string, Export<IStyleRule, StyleRuleMetadata>> languageRuleLookup = rules.ToLookup(r => r.Metadata.LanguageName); foreach (IGrouping<string, Export<IStyleRule, StyleRuleMetadata>> languageRules in languageRuleLookup) { var graph = new DirectedGraph<Export<IStyleRule, StyleRuleMetadata>>(languageRules); Dictionary<string, Export<IStyleRule, StyleRuleMetadata>> nameRuleMap = languageRules.ToDictionary(r => r.Metadata.Name); foreach (Export<IStyleRule, StyleRuleMetadata> languageRule in languageRules) { foreach (string afterName in languageRule.Metadata.AfterNames) { Export<IStyleRule, StyleRuleMetadata> afterRule; if (nameRuleMap.TryGetValue(afterName, out afterRule)) { graph.AddEdge(afterRule, languageRule); } } foreach (string beforeName in languageRule.Metadata.BeforeNames) { Export<IStyleRule, StyleRuleMetadata> beforeRule; if (nameRuleMap.TryGetValue(beforeName, out beforeRule)) { graph.AddEdge(languageRule, beforeRule); } } } IReadOnlyList<Export<IStyleRule, StyleRuleMetadata>> cycle = graph.FindCycle(); if (cycle.Count > 0) { var ruleNames = String.Join(", ", cycle.Select(r => r.Metadata.Name)); throw new InvalidOperationException($"Dependency cycle exists in rules {ruleNames}"); } languageRuleMap.Add(languageRules.Key, graph.Sort()); } return languageRuleMap; }