Project

General

Profile

root / branches / compiler / cSharp / ooasCompiler / src / libs / c5 / UserGuideExamples / Graphcopy.cs @ 3

1
/*
2
 Copyright (c) 2003-2006 Niels Kokholm <kokholm@itu.dk> and Peter Sestoft <sestoft@dina.kvl.dk>
3
 Permission is hereby granted, free of charge, to any person obtaining a copy
4
 of this software and associated documentation files (the "Software"), to deal
5
 in the Software without restriction, including without limitation the rights
6
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
 copies of the Software, and to permit persons to whom the Software is
8
 furnished to do so, subject to the following conditions:
9
 
10
 The above copyright notice and this permission notice shall be included in
11
 all copies or substantial portions of the Software.
12
 
13
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
 SOFTWARE.
20
*/
21

    
22
// C5 example: graph copying 2005-11-08
23

    
24
// Compile with 
25
//   csc /r:C5.dll Toposort.cs 
26

    
27
using System;
28
using System.Text;
29
using C5;
30
using SCG = System.Collections.Generic;
31

    
32
namespace Graphcopy {
33
  class TestGraphcopy {
34
    public static void Main(String[] args) {
35
      if (args.Length != 1) 
36
	Console.WriteLine("Usage: Graphcopy <nodecount>\n");
37
      else {
38
	int count = int.Parse(args[0]);
39
	Node<String> 
40
	  d = new Node<String>("d"), 
41
	  e = new Node<String>("e"),
42
	  c = new Node<String>("c", d, e),
43
	  b = new Node<String>("b", d),
44
	  a = new Node<String>("a", d, b, c);
45
	a[1] = a;
46
	Node<String> newstart = CopyGraph1(a);
47
	Console.WriteLine("Copy has same structure: " + Isomorphic1(newstart, a));
48
	Console.WriteLine("newstart = " + newstart);
49
	foreach (Node<String> node1 in newstart.children)
50
	  Console.WriteLine(node1);
51
	Node<String> node = new Node<String>("last");
52
	for (int i=0; i<count; i++)
53
	  node = new Node<String>(i.ToString(), node);
54
	newstart = CopyGraph1(node);
55
	Console.WriteLine("Copy has same structure: " 
56
			  + Isomorphic1(newstart, node));
57
      }
58
    }
59
    
60
    // Graph copying 0
61
    
62
    public static Node<T> CopyGraph0<T>(Node<T> start) {
63
      IDictionary<Node<T>,Node<T>> iso 
64
        = new HashDictionary<Node<T>,Node<T>>
65
              (ReferenceEqualityComparer<Node<T>>.Default);
66
      return CopyNode0(iso, start);
67
    }
68

    
69
    private static Node<T> CopyNode0<T>(IDictionary<Node<T>,Node<T>> iso, 
70
                                        Node<T> old) {
71
      Node<T> copy;
72
      if (!iso.Find(old, out copy)) {
73
        copy = new Node<T>(old);
74
        iso[old] = copy;
75
        for (int i=0; i<copy.children.Length; i++)
76
          copy.children[i] = CopyNode0(iso, old.children[i]);
77
      }
78
      return copy;
79
    }
80

    
81
    // Graph copying 1, using an explicit stack of pending nodes.
82
    // Every new node is added to the stack exactly once.  Every node
83
    // in the stack is also in the key set of the dictionary.
84
    
85
    public static Node<T> CopyGraph1<T>(Node<T> start) {
86
      IDictionary<Node<T>,Node<T>> iso 
87
        = new HashDictionary<Node<T>,Node<T>>
88
              (ReferenceEqualityComparer<Node<T>>.Default);
89
      IStack<Node<T>> work = new ArrayList<Node<T>>();
90
      iso[start] = new Node<T>(start);
91
      work.Push(start);
92
      while (!work.IsEmpty) {
93
        Node<T> node = work.Pop(), copy = iso[node];
94
        for (int i=0; i<node.children.Length; i++) {
95
          Node<T> child = node.children[i];
96
          Node<T> childCopy;
97
          if (!iso.Find(child, out childCopy)) {
98
            iso[child] = childCopy = new Node<T>(child);
99
            work.Push(child);
100
          }
101
          copy.children[i] = childCopy;
102
        }
103
      }
104
      return iso[start];
105
    }
106

    
107
    // Graph equality 0
108

    
109
    public static bool Isomorphic0<T>(Node<T> start1, Node<T> start2) {
110
      IDictionary<Node<T>,Node<T>> iso
111
        = new HashDictionary<Node<T>,Node<T>>
112
              (ReferenceEqualityComparer<Node<T>>.Default);
113
      return NodeEquals0(iso, start1, start2);
114
    }
115

    
116
    private static bool NodeEquals0<T>(IDictionary<Node<T>,Node<T>> iso, 
117
                                       Node<T> left, Node<T> rght) {
118
      Node<T> node;
119
      if (iso.Find(left, out node))
120
        return Object.ReferenceEquals(node, rght);
121
      else if (left.children.Length != rght.children.Length)
122
        return false;
123
      else {
124
        iso[left] = rght;
125
        for (int i=0; i<left.children.Length; i++)
126
          if (!NodeEquals0(iso, left.children[i], rght.children[i]))
127
            return false;
128
        return true;
129
      } 
130
    }
131

    
132
    // Graph equality 1, using an explicit stack of pending nodes.
133
    // If iso[left] = rght, we are trying to prove that left and rght
134
    // are the roots of isomorphic subgraphs.  The work stack contains
135
    // the assumptions needed to prove this.  Whenever node is on the
136
    // work stack, then node is also in the key set of iso.  
137

    
138
    public static bool Isomorphic1<T>(Node<T> start1, Node<T> start2) {
139
      IDictionary<Node<T>,Node<T>> iso
140
        = new HashDictionary<Node<T>,Node<T>>
141
              (ReferenceEqualityComparer<Node<T>>.Default);
142
      IStack<Node<T>> work = new ArrayList<Node<T>>();
143
      iso[start1] = start2;
144
      work.Push(start1);
145
      while (!work.IsEmpty) {
146
        Node<T> left = work.Pop(), rght = iso[left];
147
        if (left.children.Length != rght.children.Length)
148
          return false;
149
        else {
150
          for (int i=0; i<left.children.Length; i++) {
151
            Node<T> lchild = left.children[i], rchild = rght.children[i];
152
            Node<T> node;
153
            if (iso.Find(lchild, out node)) {
154
              if (!Object.ReferenceEquals(node, rchild))
155
                return false;
156
            } else {
157
              iso[lchild] = rchild;
158
              work.Push(lchild);
159
            }
160
          }
161
        } 
162
      }
163
      return true;
164
    }
165
  }
166

    
167
  public class Node<T> { 
168
    public readonly T id;
169
    public readonly Node<T>[] children;
170

    
171
    public Node(T id, params Node<T>[] children) { 
172
      this.id = id; this.children = children;
173
    }
174

    
175
    public Node(Node<T> node) : this(node.id, new Node<T>[node.children.Length])
176
    { }
177

    
178
    public override String ToString() { 
179
      StringBuilder sb = new StringBuilder();
180
      sb.Append(id).Append("[ ");
181
      foreach (Node<T> child in children)
182
        sb.Append(child.id).Append(" ");
183
      sb.Append("]");
184
      return sb.ToString();
185
    }
186

    
187
    public Node<T> this[int i] {
188
      set { children[i] = value; }
189
      get { return children[i]; }
190
    }
191
  }
192
}