private void BuildCoNodes (List<int> connectedComponent) { int nNodes = connectedComponent.Count; for(int i=0; i<nNodes; i++) { int curIndex=connectedComponent[i]; CoNode cur = coNodes[curIndex]; INode curNode = cur.Parent; for(int j=i; j<nNodes; j++) { int toIndex = connectedComponent[j]; CoNode to = coNodes[toIndex]; INode toNode = to.Parent; if(!nodeNeighborMap[curNode].ContainsKey(toNode)) { continue; } IEdgeList edges = nodeNeighborMap[curNode][toNode]; bool compositeEdgeIsDirected = false; foreach(var e in edges) { if(e.Type.Directedness == Directedness.Directed) { compositeEdgeIsDirected=true; } } if(compositeEdgeIsDirected) { //create two coNodes CoNode nearCur = new CoNode(); CoNode nearTo = new CoNode(); int nearCurIndex = coNodes.Count; int nearToIndex = coNodes.Count+1; coNodes.Add(nearCur); coNodes.Add(nearTo); connectedComponent.Add(nearCurIndex); connectedComponent.Add(nearToIndex); long nearCurTypeID = 1L; long nearToTypeID = 1L; foreach(var e in edges) { int baseEdgeTypeID = (int) edgeTypeNameIDMap[elementTypeNameMap[e]]; if(e.Type.Directedness==Directedness.Directed) { if(e.Source==curNode) { nearCurTypeID *= GetPrime(baseEdgeTypeID +(int)CoEdgeTypeOffsets.Head); nearToTypeID *= GetPrime(baseEdgeTypeID + (int)CoEdgeTypeOffsets.Tail); } else if(e.Target==curNode) { nearCurTypeID *= GetPrime(baseEdgeTypeID + (int)CoEdgeTypeOffsets.Tail); nearToTypeID *= GetPrime(baseEdgeTypeID + (int)CoEdgeTypeOffsets.Head); } } else if (e.Type.Directedness==Directedness.Undirected) { long edgePrime = GetPrime(baseEdgeTypeID); nearCurTypeID *= edgePrime; nearToTypeID *= edgePrime; } else { throw new Exception ("Unsupported directedness type"); } } //fill in typeids edgeCoNodeTypeIDs.Add(nearCurTypeID); edgeCoNodeTypeIDs.Add(nearToTypeID); //fill in neighbor lists cur.Neighbors.Add (nearCurIndex); nearCur.Neighbors.Add (curIndex); nearCur.Neighbors.Add (nearToIndex); nearTo.Neighbors.Add (nearCurIndex); nearTo.Neighbors.Add (toIndex); to.Neighbors.Add (nearToIndex); } else { //create just one coNode representing the undirected edge CoNode middle = new CoNode(); int middleIndex = coNodes.Count; coNodes.Add(middle); connectedComponent.Add(middleIndex); long ueTypeID = 1L; foreach(var e in edges) { long baseEdgeTypeID = GetPrime((int) edgeTypeNameIDMap[elementTypeNameMap[e]]); ueTypeID *= baseEdgeTypeID; } edgeCoNodeTypeIDs.Add(ueTypeID); //fill in the neighbors coNodes[curIndex].Neighbors.Add(middleIndex); coNodes[toIndex].Neighbors.Add(middleIndex); coNodes[middleIndex].Neighbors.Add(curIndex); coNodes[middleIndex].Neighbors.Add(toIndex); } } } }
private void BuildCoNodes(List <int> connectedComponent) { int nNodes = connectedComponent.Count; for (int i = 0; i < nNodes; ++i) { int curIndex = connectedComponent[i]; CoNode cur = coNodes[curIndex]; INode curNode = cur.Parent; for (int j = i; j < nNodes; ++j) { int toIndex = connectedComponent[j]; CoNode to = coNodes[toIndex]; INode toNode = to.Parent; if (!nodeNeighborMap[curNode].ContainsKey(toNode)) { continue; } IEdgeList edges = nodeNeighborMap[curNode][toNode]; bool compositeEdgeIsDirected = false; foreach (var e in edges) { if (e.Type.Directedness == Directedness.Directed) { compositeEdgeIsDirected = true; } } if (compositeEdgeIsDirected) { //create two coNodes CoNode nearCur = new CoNode(); CoNode nearTo = new CoNode(); int nearCurIndex = coNodes.Count; int nearToIndex = coNodes.Count + 1; coNodes.Add(nearCur); coNodes.Add(nearTo); connectedComponent.Add(nearCurIndex); connectedComponent.Add(nearToIndex); long nearCurTypeID = 1L; long nearToTypeID = 1L; foreach (var e in edges) { int baseEdgeTypeID = (int)edgeTypeNameIDMap[elementTypeNameMap[e]]; if (e.Type.Directedness == Directedness.Directed) { if (e.Source == curNode) { nearCurTypeID *= GetPrime(baseEdgeTypeID + (int)CoEdgeTypeOffsets.Head); nearToTypeID *= GetPrime(baseEdgeTypeID + (int)CoEdgeTypeOffsets.Tail); } else if (e.Target == curNode) { nearCurTypeID *= GetPrime(baseEdgeTypeID + (int)CoEdgeTypeOffsets.Tail); nearToTypeID *= GetPrime(baseEdgeTypeID + (int)CoEdgeTypeOffsets.Head); } } else if (e.Type.Directedness == Directedness.Undirected) { long edgePrime = GetPrime(baseEdgeTypeID); nearCurTypeID *= edgePrime; nearToTypeID *= edgePrime; } else { throw new Exception("Unsupported directedness type"); } } //fill in typeids edgeCoNodeTypeIDs.Add(nearCurTypeID); edgeCoNodeTypeIDs.Add(nearToTypeID); //fill in neighbor lists cur.Neighbors.Add(nearCurIndex); nearCur.Neighbors.Add(curIndex); nearCur.Neighbors.Add(nearToIndex); nearTo.Neighbors.Add(nearCurIndex); nearTo.Neighbors.Add(toIndex); to.Neighbors.Add(nearToIndex); } else { //create just one coNode representing the undirected edge CoNode middle = new CoNode(); int middleIndex = coNodes.Count; coNodes.Add(middle); connectedComponent.Add(middleIndex); long ueTypeID = 1L; foreach (var e in edges) { long baseEdgeTypeID = GetPrime((int)edgeTypeNameIDMap[elementTypeNameMap[e]]); ueTypeID *= baseEdgeTypeID; } edgeCoNodeTypeIDs.Add(ueTypeID); //fill in the neighbors coNodes[curIndex].Neighbors.Add(middleIndex); coNodes[toIndex].Neighbors.Add(middleIndex); coNodes[middleIndex].Neighbors.Add(curIndex); coNodes[middleIndex].Neighbors.Add(toIndex); } } } }
/// <summary> /// Canonize a graph /// </summary> /// <param name="graph">The graph to canonize.</param> public string Canonize (LGSPGraph graph) { elementTypeNameMap = new Dictionary<IGraphElement, string> (); //List of virtual nodes coNodes = new List<CoNode> (); nodeToCoNodeIndexMap = new Dictionary<INode, int> (); typeNames = new List<string> (); edgeTypeNames = new List<string> (); //Build virtual node(s) for each node and edge //Build the vNode -> typeID Map (2 entries for every directed edge class) foreach (var n in graph.Nodes) { string nodeTypeString = CanonizeElement (n); elementTypeNameMap [n] = nodeTypeString; if (!typeNames.Contains (nodeTypeString)) { typeNames.Add (nodeTypeString); } CoNode con = new CoNode (n); nodeToCoNodeIndexMap [n] = coNodes.Count; coNodes.Add (con); } foreach (var e in graph.Edges) { string edgeTypeString = CanonizeElement (e); elementTypeNameMap [e] = edgeTypeString; if (!edgeTypeNames.Contains (edgeTypeString)) { edgeTypeNames.Add (edgeTypeString); } } typeNames.Sort (); edgeTypeNames.Sort (); typeNameIDMap = new Dictionary<string, long> (); edgeTypeNameIDMap = new Dictionary<string, long> (); for (int i=0; i<typeNames.Count; i++) { string typeName = typeNames [i]; typeNameIDMap [typeName] = (long)i; } { //increment by 3, types reserved for undirected, tail, head int index = 0; for (int i=0; i<edgeTypeNames.Count; i++) { string edgeTypeName = edgeTypeNames [i]; edgeTypeNameIDMap [edgeTypeName] = index; index += 3; } } coNodeTypeIDs = coNodes.ConvertAll (x => 0L); foreach (var n in graph.Nodes) { int index = nodeToCoNodeIndexMap [n]; string typeName = elementTypeNameMap [n]; coNodeTypeIDs [index] = (typeNameIDMap [typeName]); } nodeNeighborMap = new Dictionary<INode, Dictionary<INode, IEdgeList>> (); //Fill in neighbormap foreach (var curNode in graph.Nodes) { Dictionary<INode, IEdgeList> neighborMap = new Dictionary<INode, IEdgeList> (); foreach (var e in curNode.Incident) { INode toNode = e.Opposite (curNode); if (!neighborMap.ContainsKey (toNode)) { neighborMap [toNode] = new IEdgeList (); } if (!neighborMap [toNode].Contains (e)) { neighborMap [toNode].Add (e); } } nodeNeighborMap [curNode] = neighborMap; } //Now every coNode corresponing to an INode has a correct typeID associated with it ... //There is a disjoint set of IDs (starting at 0) reserved in the edgeTypeNameIDMap edgeCoNodeTypeIDs = new List<long> (); Dictionary<INode, bool> visitedNodeSet = new Dictionary<INode, bool> (); connectedComponents = new List<List<int>> (); //Partition into connected components foreach (var n in graph.Nodes) { if (!visitedNodeSet.ContainsKey (n)) { visitedNodeSet [n] = true; List<int> connectedComponent = new List<int> (); BuildConnectedComponent (n, visitedNodeSet, connectedComponent); BuildCoNodes(connectedComponent); connectedComponents.Add (connectedComponent); } } if (edgeCoNodeTypeIDs.Count != 0) { PartialRankOrderList (edgeCoNodeTypeIDs); for (int i=0; i<edgeCoNodeTypeIDs.Count; i++) { edgeCoNodeTypeIDs [i] += (long)typeNames.Count; } } //Concat the edgeTypeIDs (built in RecurisveCoNodeBuild) to coNodeTypeIDs coNodeTypeIDs.AddRange(edgeCoNodeTypeIDs); List<String> connectedComponentStrings = new List<String> (connectedComponents.Count); foreach (var connectedComponent in connectedComponents) { connectedComponentStrings.Add (CanonizeConnectedComponent (connectedComponent)); } connectedComponentStrings.Sort (); StringBuilder sb = new StringBuilder (); for (int i=0; i<(connectedComponentStrings.Count-1); i++) { sb.Append (connectedComponentStrings[i] + "."); } sb.Append(connectedComponentStrings[connectedComponentStrings.Count-1]); return sb.ToString(); }
/// <summary> /// Canonize a graph /// </summary> /// <param name="graph">The graph to canonize.</param> public string Canonize(LGSPGraph graph) { elementTypeNameMap = new Dictionary <IGraphElement, string>(); //List of virtual nodes coNodes = new List <CoNode>(); nodeToCoNodeIndexMap = new Dictionary <INode, int>(); typeNames = new List <string>(); edgeTypeNames = new List <string>(); //Build virtual node(s) for each node and edge //Build the vNode -> typeID Map (2 entries for every directed edge class) foreach (var n in graph.Nodes) { string nodeTypeString = CanonizeElement(n); elementTypeNameMap[n] = nodeTypeString; if (!typeNames.Contains(nodeTypeString)) { typeNames.Add(nodeTypeString); } CoNode con = new CoNode(n); nodeToCoNodeIndexMap[n] = coNodes.Count; coNodes.Add(con); } foreach (var e in graph.Edges) { string edgeTypeString = CanonizeElement(e); elementTypeNameMap[e] = edgeTypeString; if (!edgeTypeNames.Contains(edgeTypeString)) { edgeTypeNames.Add(edgeTypeString); } } typeNames.Sort(); edgeTypeNames.Sort(); typeNameIDMap = new Dictionary <string, long>(); edgeTypeNameIDMap = new Dictionary <string, long>(); for (int i = 0; i < typeNames.Count; ++i) { string typeName = typeNames[i]; typeNameIDMap[typeName] = (long)i; } { //increment by 3, types reserved for undirected, tail, head int index = 0; for (int i = 0; i < edgeTypeNames.Count; ++i) { string edgeTypeName = edgeTypeNames[i]; edgeTypeNameIDMap[edgeTypeName] = index; index += 3; } } coNodeTypeIDs = coNodes.ConvertAll(x => 0L); foreach (var n in graph.Nodes) { int index = nodeToCoNodeIndexMap[n]; string typeName = elementTypeNameMap[n]; coNodeTypeIDs[index] = (typeNameIDMap[typeName]); } nodeNeighborMap = new Dictionary <INode, Dictionary <INode, IEdgeList> >(); //Fill in neighbormap foreach (var curNode in graph.Nodes) { Dictionary <INode, IEdgeList> neighborMap = new Dictionary <INode, IEdgeList>(); foreach (var e in curNode.Incident) { INode toNode = e.Opposite(curNode); if (!neighborMap.ContainsKey(toNode)) { neighborMap [toNode] = new IEdgeList(); } if (!neighborMap [toNode].Contains(e)) { neighborMap [toNode].Add(e); } } nodeNeighborMap[curNode] = neighborMap; } //Now every coNode corresponing to an INode has a correct typeID associated with it ... //There is a disjoint set of IDs (starting at 0) reserved in the edgeTypeNameIDMap edgeCoNodeTypeIDs = new List <long>(); Dictionary <INode, bool> visitedNodeSet = new Dictionary <INode, bool>(); connectedComponents = new List <List <int> >(); //Partition into connected components foreach (var n in graph.Nodes) { if (!visitedNodeSet.ContainsKey(n)) { visitedNodeSet[n] = true; List <int> connectedComponent = new List <int>(); BuildConnectedComponent(n, visitedNodeSet, connectedComponent); BuildCoNodes(connectedComponent); connectedComponents.Add(connectedComponent); } } if (edgeCoNodeTypeIDs.Count != 0) { PartialRankOrderList(edgeCoNodeTypeIDs); for (int i = 0; i < edgeCoNodeTypeIDs.Count; ++i) { edgeCoNodeTypeIDs[i] += (long)typeNames.Count; } } //Concat the edgeTypeIDs (built in RecurisveCoNodeBuild) to coNodeTypeIDs coNodeTypeIDs.AddRange(edgeCoNodeTypeIDs); List <String> connectedComponentStrings = new List <String>(connectedComponents.Count); foreach (var connectedComponent in connectedComponents) { connectedComponentStrings.Add(CanonizeConnectedComponent(connectedComponent)); } connectedComponentStrings.Sort(); StringBuilder sb = new StringBuilder(); for (int i = 0; i < (connectedComponentStrings.Count - 1); ++i) { sb.Append(connectedComponentStrings[i] + "."); } sb.Append(connectedComponentStrings[connectedComponentStrings.Count - 1]); return(sb.ToString()); }