private void FindGraphCycles(out List <Stack <ParsedCell> > cycles) { cycles = new List <Stack <ParsedCell> >(); var unvisited = new HashSet <ParsedCell>(cellGraph.Keys); while (unvisited.Count > 0) { ParsedCell curNode = null; foreach (var node in unvisited) { curNode = node; break; } var path = new Stack <ParsedCell>(); if (HasCycleWithNode(path, new HashSet <ParsedCell>(), curNode, curNode)) { cycles.Add(path); foreach (var node in path) { unvisited.Remove(node); } } else { unvisited.Remove(curNode); } } }
private void RemoveParentFromChildren(ParsedCell parent) { if (!cellGraph.ContainsKey(parent)) { return; } var children = cellGraph[parent].children; foreach (var child in children) { if (!cellGraph.ContainsKey(child)) { continue; } var childNode = cellGraph[child]; if (!childNode.parents.Contains(parent)) { continue; } childNode.parents.Remove(parent); if (childNode.parents.Count == 0 && childNode.children.Count == 0) { cellGraph.Remove(child); } } }
private void ListenToChildsErrors(ParsedCell listener) { Debug.Assert(cellGraph.ContainsKey(listener)); SubscribeToChildError(new HashSet <ParsedCell>() { listener }, cellGraph[listener].children, listener); }
private void AddParentToChildren(ParsedCell parent, HashSet <ParsedCell> children) { foreach (var child in children) { if (!cellGraph.ContainsKey(child)) { cellGraph.Add(child, (new HashSet <ParsedCell>(), new HashSet <ParsedCell>())); } cellGraph[child].parents.Add(parent); } }
private void SpreadErrorFromCell(ParsedCell cell, GridCoordinates cords) { if (!spreadErrorListeners.ContainsKey(cords)) { spreadErrorListeners.Add(cords, new HashSet <ParsedCell>()); } SpreadToParents(new HashSet <ParsedCell> { cell }, cellGraph[cell].parents, cords); }
private void CalculateGrid() { var childDictionary = new Dictionary <GridCoordinates, object>(); var unvisited = new HashSet <ParsedCell>(cellGraph.Keys.Where((cell) => cell.Calculable)); while (unvisited.Count > 0) { ParsedCell targetCell = null; foreach (var cell in unvisited) { targetCell = cell; break; } TryCalculateCell(unvisited, childDictionary, targetCell); } }
private string GenerateCycleErrorMessage(Stack <ParsedCell> path, ParsedCell initCell) { var sb = new StringBuilder(); sb.Append("Recursive dependency: \n"); var pathList = new List <ParsedCell>(path); var shift = pathList.IndexOf(initCell); Debug.Assert(shift >= 0); for (int i = 0; i < pathList.Count; i++) { var cell = pathList[(shift + pathList.Count - i) % pathList.Count]; (string x, string y) = cell.Coordinates.GetStringCoords(); sb.Append($"{x}{y} "); } return(sb.ToString()); }
private void UpdateGraphForCell(ParsedCell targetCell) { if (!cellGraph.ContainsKey(targetCell)) { cellGraph.Add(targetCell, (new HashSet <ParsedCell>(), new HashSet <ParsedCell>())); } else { RemoveParentFromChildren(targetCell); cellGraph[targetCell].children.Clear(); } cellGraph[targetCell].children.UnionWith(ExtractCellsFromCoords(targetCell.ChildCells)); AddParentToChildren(targetCell, cellGraph[targetCell].children); if (cellGraph[targetCell].children.Count == 0 && cellGraph[targetCell].parents.Count == 0) { cellGraph.Remove(targetCell); } }
private bool HasCycleWithNode(Stack <ParsedCell> path, HashSet <ParsedCell> visited, ParsedCell currCell, ParsedCell initCell) { if (visited.Contains(currCell)) { return(false); } visited.Add(currCell); path.Push(currCell); foreach (var child in cellGraph[currCell].children) { if (child == initCell) { return(true); } if (visited.Contains(child)) { continue; } if (HasCycleWithNode(path, visited, child, initCell)) { return(true); } } path.Pop(); return(false); }
private void SubscribeToChildError(HashSet <ParsedCell> visited, HashSet <ParsedCell> children, ParsedCell initListener) { foreach (var child in children) { if (visited.Contains(child)) { continue; } visited.Add(child); if (child.HasError) { var childCords = child.Coordinates; if (!spreadErrorListeners.ContainsKey(childCords)) { spreadErrorListeners.Add(childCords, new HashSet <ParsedCell>()); } initListener.AddSpreadErrorSource(childCords); spreadErrorListeners[childCords].Add(initListener); } else { Debug.Assert(cellGraph.ContainsKey(child)); SubscribeToChildError(visited, cellGraph[child].children, initListener); } } }
private bool TryCalculateCell(HashSet <ParsedCell> unvisited, Dictionary <GridCoordinates, object> calculated, ParsedCell curCell) { unvisited.Remove(curCell); bool success = true; foreach (GridCoordinates childCoords in curCell.ChildCells) { if (calculated.ContainsKey(childCoords)) { continue; } var childCell = FromCoords(childCoords); if (childCell == null) { calculated.Add(childCoords, (Decimal)0); } if (unvisited.Contains(childCell)) { success &= TryCalculateCell(unvisited, calculated, childCell); } } if (success) { var result = curCell.Calculate(calculated); calculated.Add(curCell.Coordinates, curCell.Value); return(result); } return(false); }