public void IsoSingleNodeUllmann() { Vertex root1 = 1;// new ObjectId(new Symbol("Root"), 1); VertexData vd1 = new VertexData(); Vertex root2 = 1;// new ObjectId(new Symbol("Root"), 1); VertexData vd2 = new VertexData(); Dictionary<Vertex, VertexData> vr1 = new Dictionary<Vertex, VertexData>(); vr1.Add(root1, vd1); Dictionary<Vertex, VertexData> vr2 = new Dictionary<Vertex, VertexData>(); vr2.Add(root1, vd2); RootedLabeledDirectedGraph g1 = new RootedLabeledDirectedGraph(root1, vr1); RootedLabeledDirectedGraph g2 = new RootedLabeledDirectedGraph(root2, vr2); Map<Vertex, Vertex> iso = GraphIsomorphism.ComputeIsomorphismUllmann(g1, g2); Assert.AreEqual(1, iso.Count); }
internal IterativeIsomorphismExtensionWithBacktrackingAndPartitioning(RootedLabeledDirectedGraph g1, RootedLabeledDirectedGraph g2, Dictionary<NodeLabel, Bucket> bucketOf) { this.g1 = g1; this.g2 = g2; this.bijection = new Node[g1.vertexRecords.Count,2]; this.x = g1.root; this.y = g2.root; this.bucketOf = bucketOf; this.numberOfNodes = g1.vertexRecords.Count; }
/// <summary> /// Returns an isomorphism from g1 to g2, if g1 and g2 are isomorphic; /// returns null, otherwise. /// /// Implements a backtracking extension of the linearization algorithm for /// rooted directed ordered labelled graphs. /// The algorithm uses optimizations that rely on strong /// objectid independent hashing. /// /// (This version does not use partitioning) /// </summary> public static Map<Node, Node> ComputeIsomorphism2(RootedLabeledDirectedGraph g1, RootedLabeledDirectedGraph g2) { GraphIsomorphism gi = new GraphIsomorphism(g1, g2); return gi.ComputeIsomorphism2(); }
GraphIsomorphism(RootedLabeledDirectedGraph g1, RootedLabeledDirectedGraph g2) { this.g1 = g1; this.g2 = g2; }
// this is currently too general. It should rather work on a partition. /// <summary> /// A node n is order-independent in g if all nodes in /// its neighborhood are in singleton buckets /// </summary> bool IsOrderIndependent(Node n, RootedLabeledDirectedGraph g) { if (orderIndependent.ContainsKey(n)) return orderIndependent[n]; VertexData nData = g.vertexRecords[n]; foreach (Pair<CompoundTerm, Node> edge in nData.incomingEdges) if (bucketOf[g.LabelOf(edge.Second)].Size > 1) { orderIndependent.Add(n, false); return false; } foreach (Pair<CompoundTerm, Node> edge in nData.orderedOutgoingEdges) if (bucketOf[g.LabelOf(edge.Second)].Size > 1) { orderIndependent.Add(n, false); return false; } foreach (Pair<CompoundTerm, Set<Node>> edge in nData.unorderedOutgoingEdges) foreach (Node x1 in edge.Second) if (bucketOf[g.LabelOf(x1)].Size > 1) { orderIndependent.Add(n, false); return false; } orderIndependent.Add(n, true); return true; }
//private class NodePartition : SortedList<Node, object> //{ // internal bool independent; // internal NodePartition(Node x, bool independent) // : base() // { // base.Add(x, null); // this.independent = independent; // } // internal void AddNode(Node x) // { // base.Add(x, null); // } // internal IList<Node> Nodes // { // get // { // return base.Keys; // } // } //} /// <summary> /// Partition the set of neighbors of all outgoing unordered edges of a node x in g. /// Returns all the partitions indexed by the pair (E,L) where /// E is an edge label and L is the label of the neighbor. /// /// A partition is marked order-independent if some node in that partition is /// order-independent, which implies that all nodes in the same partition must be /// order-independent as well (this is a property implied by the node labeling/hashing algorithm). /// </summary> /// <param name="g">given graph</param> /// <param name="node">given node in g</param> /// <param name="edgeLabel">given edge label</param> static Map<Pair<IComparable, bool>, Set<Node>> GetPartitions(RootedLabeledDirectedGraph g, Node node, CompoundTerm edgeLabel) { Map<Pair<IComparable,bool>, Set<Node>> partitions = Map<Pair<IComparable,bool>, Set<Node>>.EmptyMap; VertexData xData1 = g.vertexRecords[node]; // xData is already in context. foreach (Node x1 in xData1.unorderedOutgoingEdges[edgeLabel]) { Pair<IComparable, bool> key = new Pair<IComparable, bool>(g.LabelOf(x1), true);//IsOrderIndependent(x1, g)); Set<Node> nodePartition; if (partitions.TryGetValue(key, out nodePartition)) partitions=partitions.Override(key,nodePartition.Add(x1)); else partitions=partitions.Add(key, new Set<Node>(x1)); } return partitions; }