134 TYPE(
vertex),
DIMENSION(:),
INTENT(IN) :: reference, unordered
135 INTEGER,
DIMENSION(:),
INTENT(OUT) :: order
136 LOGICAL,
INTENT(OUT) :: matches
138 INTEGER,
PARAMETER :: max_tries = 1000000
140 INTEGER :: hash_re, hash_un, i, iclass, iele, &
141 isuperclass, itries, j, n, nclasses, &
143 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: class_of_atom, index_ref, index_un, &
144 kind_ref, kind_ref_ordered, kind_un, &
145 kind_un_ordered, superclass_of_atom
146 TYPE(class),
ALLOCATABLE,
DIMENSION(:) :: classes
147 TYPE(superclass),
ALLOCATABLE,
DIMENSION(:) :: superclasses
154 IF (
SIZE(reference) .NE.
SIZE(unordered))
THEN
161 order = (/(i, i=1, n)/)
162 IF (matrix_equal(reference, unordered, order))
THEN
168 ALLOCATE (kind_ref(n), kind_un(n), index_ref(n), index_un(n), &
169 kind_ref_ordered(n), kind_un_ordered(n), &
170 class_of_atom(n), superclass_of_atom(n))
173 IF (hash_re .NE. hash_un)
THEN
179 kind_ref_ordered(:) = kind_ref
180 CALL sort(kind_ref_ordered, n, index_ref)
181 kind_un_ordered(:) = kind_un
182 CALL sort(kind_un_ordered, n, index_un)
183 IF (any(kind_ref_ordered .NE. kind_un_ordered))
THEN
190 old_class = kind_ref_ordered(1)
192 IF (kind_ref_ordered(i) .NE. old_class)
THEN
193 nclasses = nclasses + 1
194 old_class = kind_ref_ordered(i)
197 ALLOCATE (classes(nclasses))
198 classes(1)%kind = kind_ref_ordered(1)
202 IF (kind_ref_ordered(i) .NE. classes(nclasses)%kind)
THEN
203 nclasses = nclasses + 1
204 classes(nclasses)%kind = kind_ref_ordered(i)
205 classes(nclasses)%Nele = 1
207 classes(nclasses)%Nele = classes(nclasses)%Nele + 1
214 nele = classes(i)%Nele
215 ALLOCATE (classes(i)%reference(nele))
216 ALLOCATE (classes(i)%unordered(nele))
219 classes(i)%reference(j) = index_ref(iele)
220 classes(i)%unordered(j) = index_un(iele)
222 class_of_atom(classes(i)%reference) = i
223 ALLOCATE (classes(i)%order(nele))
224 ALLOCATE (classes(i)%q(nele))
225 classes(i)%order = (/(j, j=1, nele)/)
226 classes(i)%first = .true.
233 superclass_of_atom = -1
237 IF (superclass_of_atom(i) .EQ. -1 .AND. classes(class_of_atom(i))%Nele > 1)
THEN
238 isuperclass = isuperclass + 1
239 CALL spread_superclass(i, isuperclass, superclass_of_atom, class_of_atom, classes, reference)
244 ALLOCATE (superclasses(isuperclass))
245 superclasses%Nele = 0
247 j = superclass_of_atom(classes(i)%reference(1))
248 IF (j > 0) superclasses(j)%Nele = superclasses(j)%Nele + 1
250 DO i = 1, isuperclass
251 ALLOCATE (superclasses(i)%classes(superclasses(i)%Nele))
252 superclasses(i)%Nele = 0
255 j = superclass_of_atom(classes(i)%reference(1))
257 superclasses(j)%Nele = superclasses(j)%Nele + 1
258 superclasses(j)%classes(superclasses(j)%Nele) = i
267 DO iclass = 1, nclasses
268 order(classes(iclass)%unordered) = classes(iclass)%reference(classes(iclass)%order)
273 DO i = 1, isuperclass
278 DO iclass = 1, superclasses(i)%Nele
279 j = superclasses(i)%classes(iclass)
280 order(classes(j)%unordered) = classes(j)%reference(classes(j)%order)
284 matches = matrix_superclass_equal(reference, unordered, order, superclasses(i), classes)
285 IF (itries > max_tries)
THEN
286 WRITE (*, *)
"Could not find the 1-to-1 mapping to prove graph isomorphism"
287 WRITE (*, *)
"Reordering failed, assuming these molecules are different"
293 DO iclass = 1, superclasses(i)%Nele
294 j = superclasses(i)%classes(iclass)
295 CALL all_permutations(classes(j)%order, classes(j)%Nele, &
296 classes(j)%q, classes(j)%first)
297 IF (.NOT. classes(j)%first)
EXIT
301 IF (iclass .EQ. superclasses(i)%Nele .AND. &
302 classes(superclasses(i)%classes(superclasses(i)%Nele))%first)
EXIT
305 IF (.NOT. matches)
EXIT
309 matches = matrix_equal(reference, unordered, order)
311 DO iclass = 1, nclasses
312 DEALLOCATE (classes(iclass)%reference)
313 DEALLOCATE (classes(iclass)%unordered)
314 DEALLOCATE (classes(iclass)%order)
315 DEALLOCATE (classes(iclass)%q)
318 DO i = 1, isuperclass
319 DEALLOCATE (superclasses(i)%classes)
321 DEALLOCATE (superclasses)