using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using CaeGlobals; namespace CaeMesh { public class Graph where T : IComparable { // Variables private NodeList _nodeList; // Properties public NodeList Nodes { get { return _nodeList; } } public int Count { get { return _nodeList.Count; } } // Constructors public Graph() { _nodeList = new NodeList(); } public Graph(Graph graph) : this(graph.Nodes) { } public Graph(NodeList nodeList) { _nodeList = new NodeList(); // if (nodeList != null) { Node newNode; Dictionary, Node> oldNewNode = new Dictionary, Node>(); // Create new nodes foreach (var oldNode in nodeList) { newNode = new Node(oldNode.Value); AddNode(newNode); oldNewNode.Add(oldNode, newNode); } // Add connections foreach (var oldNode in nodeList) { foreach (var neighbour in oldNode.Neighbours) { AddDirectedEdge(oldNewNode[oldNode], oldNewNode[neighbour]); } } } } // Methods public void AddNode(Node node) { // Adds a node to the graph _nodeList.Add(node); } public bool Contains(T value) { return _nodeList.FindByValue(value) != null; } public bool Remove(T value) { // First remove the node from the nodeList Node nodeToRemove = _nodeList.FindByValue(value); return Remove(nodeToRemove); } public bool Remove(Node node) { if (node == null) return false; // Remove the node _nodeList.Remove(node); // Enumerate through each node in the nodeList, removing edges to this node foreach (Node gnode in _nodeList) { int index = gnode.Neighbours.IndexOf(node); if (index != -1) { // Remove the reference to the node and associated cost gnode.Neighbours.RemoveAt(index); } } // return true; } public T[] GetValues() { int count = 0; T[] values = new T[_nodeList.Count]; foreach (var item in _nodeList) { values[count++] = item.Value; } return values; } // Edges public void AddDirectedEdge(Node from, Node to) { from.Neighbours.Add(to); } public void AddUndirectedEdge(Node from, Node to) { from.Neighbours.Add(to); to.Neighbours.Add(from); } public void RemoveDirectedEdge(Node from, Node to) { from.Neighbours.Remove(to); } public void RemoveUndirectedEdge(Node from, Node to) { from.Neighbours.Remove(to); to.Neighbours.Remove(from); } // public bool IsGraphWithoutCycles() { Node currentNode; Node parentNode; Queue> queue = new Queue>(); Queue> parentQueue = new Queue>(); HashSet> visitedNodes = new HashSet>(); // queue.Enqueue(_nodeList.First()); parentQueue.Enqueue(_nodeList.First()); // while (queue.Count() > 0) { currentNode = queue.Dequeue(); parentNode = parentQueue.Dequeue(); // Check for cycles if (visitedNodes.Add(currentNode)) { // Add all neighbours to the queue foreach (var neighbour in currentNode.Neighbours) { if (neighbour != parentNode) { queue.Enqueue(neighbour); parentQueue.Enqueue(currentNode); } } } else return false; } return true; } public bool IsGraphWithOneCycle() { Graph graphCopy = new Graph(_nodeList); List singleConnectedItems = new List(); // Remove all open branches do { singleConnectedItems.Clear(); // foreach (Node node in graphCopy.Nodes) { if (node.Neighbours.Count() <= 1) singleConnectedItems.Add(node.Value); } // foreach (var item in singleConnectedItems) { graphCopy.Remove(item); } } while (singleConnectedItems.Count > 0); // Check for a single cycle foreach (Node node in graphCopy.Nodes) { if (node.Neighbours.Count() > 2) return false; } return true; } public List> GetConnectedSubgraphs() { Node currentNode; HashSet> visitedNodes = new HashSet>(); Queue> queue = new Queue>(); NodeList connectedNodes; List> connectedSubgraphs = new List>(); // Sort try { _nodeList.Sort(); } catch { } // foreach (var node in _nodeList) { // Check if the node was already added if (!visitedNodes.Contains(node)) { // Create new set of connected nodes connectedNodes = new NodeList(); // queue.Enqueue(node); // Search for connected nodes while (queue.Count() > 0) { currentNode = queue.Dequeue(); if (visitedNodes.Add(currentNode)) { connectedNodes.Add(currentNode); // Add all neighbours to the queue foreach (var neighbour in currentNode.Neighbours) queue.Enqueue(neighbour); } } // connectedSubgraphs.Add(new Graph(connectedNodes)); } } // return connectedSubgraphs; } // For unidirected graphs public List GetIndependencyList() { Graph graphCopy = new Graph(_nodeList); List childItems = new List(); List independencyList = new List(); // Remove all independent items do { childItems.Clear(); // foreach (Node node in graphCopy.Nodes) { if (node.Neighbours.Count() == 0) childItems.Add(node.Value); } // foreach (var item in childItems) { graphCopy.Remove(item); } independencyList.AddRange(childItems); } while (childItems.Count > 0); // if (graphCopy.Count > 0) throw new NotSupportedException(); // return independencyList; } } }