public GraphEdge(GraphNode node1, GraphNode node2) {
            if (node1 == null || node2 == null) {
                throw new InvalidOperationException("Cannot add an edge if one or more of the nodes doesnt exist.");
            }

            node1.edges.Add(this);
            node2.edges.Add(this);
            node1.neighbors.Add(node2);
            node2.neighbors.Add(node1);
            this.node1 = node1;
            this.node2 = node2;
            weight = 0;
        }
 public GraphEdge(GraphNode node1, GraphNode node2, int weight) : this(node1, node2) {
     this.weight = weight;
 }
        public override void CreateEdge(GraphNode node1, GraphNode node2) {
            if (!nodes.Contains(node1) || !nodes.Contains(node2)) {
                throw new InvalidOperationException("Cannot add an edge if one or more of the nodes arent in the graph.");
            }

            if (node1.edges.Count > 0 && node2.edges.Count > 0) {
                throw new InvalidOperationException("Can't create an edge between nodes that are already connected to tree.");
            }

            GraphEdge newEdge = new GraphEdge(node1, node2);
            edges.Add(newEdge);
            nodeToEdgeDict[CombineHashes(node1, node2)]  = newEdge;
        }
 public IntVector2 GetNodeCoords(GraphNode n) {
     return nodeToCoordinates[n];
 }
 private void InitNodes() {
     for (int i = 0; i < sizeX; i++) {
         for (int j = 0; j < sizeY; j++) {
             grid[i, j] = new GraphNode();
             AddNode(grid[i, j]);
             nodeToCoordinates[grid[i, j]] = new IntVector2(i, j);
         }
     }
 }
        public Dictionary<GraphNode, Path> GetShortestPathsForTree(GraphNode startNode) {
            var pathDict = new Dictionary<GraphNode, Path>();
            var nodeQ = new Queue<GraphNode>();
            nodeQ.Enqueue(startNode);

            pathDict[startNode] = new Path(new List<GraphNode> { startNode }, 0);

            while (nodeQ.Count > 0) {
                GraphNode currentNode = nodeQ.Dequeue();

                List<GraphNode> nextNodes = currentNode.neighbors;

                Path currentPath = pathDict[currentNode];
                foreach (var n in nextNodes) {
                    if (!pathDict.ContainsKey(n)) {
                        pathDict[n] = currentPath.Copy();
                        pathDict[n].pathLength += 1;
                        pathDict[n].nodeList.Add(n);
                        nodeQ.Enqueue(n);
                    }
                }
            }

            return pathDict;
        }
 public virtual void RemoveNode(GraphNode n) {
     nodes.Remove(n);
     nodeDict.Remove(n);
 }
        //remove an edge based on the two nodes in the edge (overload of above)
        public virtual void RemoveEdge(GraphNode n1, GraphNode n2) {
            GraphEdge edge = GetEdge(n1, n2);

            if (edge == null) {
                return;
            }

            n1.edges.Remove(edge);
            n2.edges.Remove(edge);
            n1.neighbors.Remove(n2);
            n2.neighbors.Remove(n1);
            edges.Remove(edge);
            nodeToEdgeDict.Remove(CombineHashes(n1, n2));
        }
 //get an edge based on the two nodes in the edge
 public virtual GraphEdge GetEdge(GraphNode n1, GraphNode n2) { 
     try {
         return nodeToEdgeDict[CombineHashes(n1, n2)];
     }
     catch {
         return null;
     }
 }
        //add a node to the graph
        public virtual void AddNode(GraphNode node) {
            if (node == null) {
                throw new InvalidOperationException("Trying to add null node to the graph.");
            }

            nodes.Add(node);
            nodeDict.Add(node, true);
        }
        //Creates an edge in the graph between the two given nodes, if they exist in the graph
        public virtual void CreateEdge(GraphNode node1, GraphNode node2) {
            if (!nodes.Contains(node1) || !nodes.Contains(node2)) {
                throw new InvalidOperationException("Cannot add an edge if one or more of the nodes arent in the graph.");
            }

            GraphEdge newEdge = new GraphEdge(node1, node2);
            edges.Add(newEdge);

            try {
                nodeToEdgeDict.Add(CombineHashes(node1, node2), newEdge);
            }
            catch(ArgumentException)  {
                Debug.Log("hash collision: " + node1.GetHashCode().ToString() + " " + node2.GetHashCode().ToString() 
                    + " " + CombineHashes(node1, node2).ToString());
                Debug.Log(nodeToEdgeDict[CombineHashes(node1, node2)].ToString());
                return;
            }

        }
        //Basic graph functions:

        //combines hashes of two nodes for purposes of retrieving edge from nodeToEdge dict
        protected long CombineHashes(GraphNode obj1, GraphNode obj2) {
            long code1 = (long)obj2.GetHashCode(), code2 = (long)obj1.GetHashCode(), swap;
            if (code1 > code2) {
                swap = code1;
                code1 = code2;
                code2 = swap;
            }
            long hash = 17;
            hash = hash * 31 + code1;
            hash = hash * 31 + code2;
            return hash;
        }