/* ==========================================
* JGraphT : a free Java graph-theory library
* ==========================================
*
* Project Info: http://jgrapht.sourceforge.net/
* Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh)
*
* (C) Copyright 2003-2008, by Barak Naveh and Contributors.
*
* This program and the accompanying materials are dual-licensed under
* either
*
* (a) the terms of the GNU Lesser General Public License version 2.1
* as published by the Free Software Foundation, or (at your option) any
* later version.
*
* or (per the licensee's choosing)
*
* (b) the terms of the Eclipse Public License v1.0 as published by
* the Eclipse Foundation.
*/
/* -----------------
* IsomorphismInspectorTest.java
* -----------------
* (C) Copyright 2005-2008, by Assaf Lehr and Contributors.
*
* Original Author: Assaf Lehr
* Contributor(s): -
*
* $Id$
*
* Changes
* -------
*/
package org.jgrapht.experimental.isomorphism;
import java.util.*;
import junit.framework.*;
import org.jgrapht.*;
import org.jgrapht.experimental.equivalence.*;
import org.jgrapht.experimental.isomorphism.comparators.*;
import org.jgrapht.generate.*;
import org.jgrapht.graph.*;
/**
* @author Assaf
* @since May 27, 2005
*/
public class IsomorphismInspectorTest
extends TestCase
{
//~ Constructors -----------------------------------------------------------
/**
* Constructor for IsomorphismInspectorTest.
*
* @param arg0
*/
public IsomorphismInspectorTest(String arg0)
{
super(arg0);
}
//~ Methods ----------------------------------------------------------------
/*
* @see TestCase#setUp()
*/
protected void setUp()
throws Exception
{
super.setUp();
}
/**
* Calls the same method with different (default) parameters
* EqualityGroupChecker vertexChecker = null EqualityGroupChecker
* edgeChecker = null
*/
private void assertIsomorphic(
Graph<Integer, DefaultEdge> [] graphs,
boolean shouldTheyBeIsomorphic)
{
assertIsomorphic(graphs, shouldTheyBeIsomorphic, null, null);
}
@SuppressWarnings("unchecked")
private void assertIsomorphic(
Graph<Integer, DefaultEdge> [] graphs,
boolean shouldTheyBeIsomorphic,
EquivalenceComparator vertexChecker,
EquivalenceComparator edgeChecker)
{
// System.out.println("\nassertIsomorphic:"+shouldTheyBeIsomorphic);
Graph<Integer, DefaultEdge> g1 = graphs[0];
Graph<Integer, DefaultEdge> g2 = graphs[1];
// System.out.println("g1:"+g1);
// System.out.println("g2:"+g2);
// long beforeTime=System.currentTimeMillis();
GraphIsomorphismInspector iso =
AdaptiveIsomorphismInspectorFactory.createIsomorphismInspector(
g1,
g2,
vertexChecker,
edgeChecker);
int counter = 0;
while (iso.hasNext()) {
IsomorphismRelation isioResult = (IsomorphismRelation) iso.next();
if (false) {
if (counter == 0) {
System.out.println(
"Graphs are isomorphic. Iterating over all options:");
}
System.out.println(counter + " : " + isioResult);
}
counter++;
}
// if (counter==0)
// {
// System.out.println("Graphs are NOT isomorphic.");
// }
// long deltaTime=System.currentTimeMillis()-beforeTime;
// String timeDesc;
// timeDesc= deltaTime<=10 ? "<10ms [less than minimum measurement
// time]": String.valueOf(deltaTime);
// System.out.println("# Performence: Isomorphism check in
// MiliSeconds:"+timeDesc);
if (shouldTheyBeIsomorphic) {
assertTrue(counter != 0);
} else {
assertTrue(counter == 0);
}
}
@SuppressWarnings("unchecked")
private void checkRelation(
Graph<Integer, DefaultEdge> [] graphs,
EquivalenceComparator vertexChecker,
EquivalenceComparator edgeChecker)
{
Graph<Integer, DefaultEdge> g1 = graphs[0];
Graph<Integer, DefaultEdge> g2 = graphs[1];
GraphIsomorphismInspector iso =
AdaptiveIsomorphismInspectorFactory.createIsomorphismInspector(
g1,
g2,
vertexChecker,
edgeChecker);
IsomorphismRelation<Integer, DefaultEdge> isoResult;
if (iso.hasNext()) {
isoResult = (IsomorphismRelation) iso.next();
Set<Integer> vertexSet = g1.vertexSet();
for (
Iterator<Integer> iter = vertexSet.iterator();
iter.hasNext();)
{
Integer v1 = iter.next();
Integer v2 = isoResult.getVertexCorrespondence(v1, true);
if (false) {
System.out.println("Vertex relation " + v1 + " to " + v2);
}
}
Set<DefaultEdge> edgeSet = g1.edgeSet();
for (
Iterator<DefaultEdge> iter = edgeSet.iterator();
iter.hasNext();)
{
DefaultEdge e1 = iter.next();
DefaultEdge e2 = isoResult.getEdgeCorrespondence(e1, true);
if (false) {
System.out.println("Vertex relation " + e1 + " to " + e2);
}
}
// if (counter==0)
// {
// System.out.println("Graphs are isomorphic. Iterating over all
// options:");
// }
// System.out.println(counter+" : "+isioResult);
}
}
@SuppressWarnings("unchecked")
public void testWheelGraphAddRemoveParts()
{
final int NUM_OF_VERTEXES_IN_WHEEL = 6;
final int FIRST_INTEGER_FOR_G2 = 13;
Graph<Integer, DefaultEdge> g1 =
new DefaultDirectedGraph<Integer, DefaultEdge>(
DefaultEdge.class);
Graph<Integer, DefaultEdge> g2 =
new DefaultDirectedGraph<Integer, DefaultEdge>(
DefaultEdge.class);
WheelGraphGenerator<Integer, DefaultEdge> gen1 =
new WheelGraphGenerator<Integer, DefaultEdge>(
NUM_OF_VERTEXES_IN_WHEEL);
gen1.generateGraph(g1, new IntegerVertexFactory(), null);
// FIRST_INTEGER_FOR_G2-1 , cause first integer is always the next one.
gen1.generateGraph(
g2,
new IntegerVertexFactory(FIRST_INTEGER_FOR_G2),
null);
assertIsomorphic(
new Graph[] {
g1,
g2
},
true);
// In a wheel , the last vertex is the wheel center!
g1.removeVertex(new Integer(NUM_OF_VERTEXES_IN_WHEEL)); // delete one vertex from g1
assertIsomorphic(
new Graph[] {
g1,
g2
},
false);
// for example: 10+4
g2.removeVertex(
new Integer(FIRST_INTEGER_FOR_G2
+ NUM_OF_VERTEXES_IN_WHEEL));
assertIsomorphic(
new Graph[] {
g1,
g2
},
true);
g1.removeEdge(new Integer(1), new Integer(2));
assertIsomorphic(
new Graph[] {
g1,
g2
},
false);
}
@SuppressWarnings("unchecked")
public void testLinear4vertexIsomorphicGraph()
{
Graph<Integer, DefaultEdge> g1 =
new DefaultDirectedGraph<Integer, DefaultEdge>(
DefaultEdge.class);
LinearGraphGenerator gen1 = new LinearGraphGenerator(4);
gen1.generateGraph(g1, new IntegerVertexFactory(), null);
Graph<Integer, DefaultEdge> g2 =
new DefaultDirectedGraph<Integer, DefaultEdge>(
DefaultEdge.class);
LinearGraphGenerator gen2 = new LinearGraphGenerator(4);
gen2.generateGraph(g2, new IntegerVertexFactory(5), null); // start vertex from number 6
assertIsomorphic(
new Graph[] {
g1,
g2
},
true);
checkRelation(
new Graph[] {
g1,
g2
},
null,
null);
}
/**
* Create two graphs which are topologically the same (same number of
* vertexes and same edges connection), but the contents of the vertexes
* belong to different eq. set. g1: 1-->2-->3-->4 g2: 2-->3-->4-->5 g3:
* 3-->4-->5-->6 The eq-group-check is if the number is even or odd. So, g1
* and g3 are isomorphic. g2 is not isomorphic to either of them.
*/
@SuppressWarnings("unchecked")
public void testLinear4vertexNonIsomorphicCauseOfVertexEqGroup()
{
LinearGraphGenerator<Integer, DefaultEdge> gen4 =
new LinearGraphGenerator<Integer, DefaultEdge>(4);
Graph<Integer, DefaultEdge> g1 =
new DefaultDirectedGraph<Integer, DefaultEdge>(
DefaultEdge.class);
gen4.generateGraph(g1, new IntegerVertexFactory(), null);
Graph<Integer, DefaultEdge> g2 =
new DefaultDirectedGraph<Integer, DefaultEdge>(
DefaultEdge.class);
gen4.generateGraph(g2, new IntegerVertexFactory(1), null); // start vertex from number 2
Graph<Integer, DefaultEdge> g3 =
new DefaultDirectedGraph<Integer, DefaultEdge>(
DefaultEdge.class);
gen4.generateGraph(g3, new IntegerVertexFactory(2), null); // start vertex from number 3
// first assert all are isomorphic (if vertexChecker is not used)
assertIsomorphic(
new Graph[] {
g1,
g2
},
true);
assertIsomorphic(
new Graph[] {
g2,
g3
},
true);
assertIsomorphic(
new Graph[] {
g1,
g3
},
true);
// create a functor according to odd even
EquivalenceComparator vertexEqChecker = new OddEvenGroupComparator();
assertIsomorphic(
new Graph[] {
g1,
g2
},
false,
vertexEqChecker,
null);
assertIsomorphic(
new Graph[] {
g2,
g3
},
false,
vertexEqChecker,
null);
assertIsomorphic(
new Graph[] {
g1,
g3
},
true,
vertexEqChecker,
null);
}
/**
* Passes an EdgeComparator, which compares according to odd-even edge
* weight. The generated graphs are: A-(12)->B-(10)->C-(5)->D
* A-(10)->B-(18)->C-(3)->D A-(11)->B-(10)->C-(5)->D (the first here is odd)
*
* @author Assaf
* @since Aug 12, 2005
*/
@SuppressWarnings("unchecked")
public void testEdgeComparator()
{
int LINEAR_GRAPH_VERTEX_NUM = 4;
Graph [] graphsArray = new DirectedGraph[3];
Character [] charArray =
new Character[] {
new Character('A'),
new Character('B'),
new Character('C'),
new Character('D')
};
int [][] weigthsArray =
new int[][] {
{
12,
10,
5
},
{
10,
18,
3
},
{
11,
10,
5
}
};
for (int i = 0; i < graphsArray.length; i++) {
Graph<Character, DefaultEdge> currGraph =
graphsArray[i] =
new DefaultDirectedWeightedGraph<Character,
DefaultWeightedEdge>(
DefaultWeightedEdge.class);
for (int j = 0; j < LINEAR_GRAPH_VERTEX_NUM; j++) {
currGraph.addVertex(charArray[j]);
}
// create the 3 edges with weights
for (int j = 0; j < 3; j++) {
Graphs.addEdge(
currGraph,
charArray[j],
charArray[j + 1],
weigthsArray[i][j]);
}
}
// first assert all are isomorphic (if vertexChecker is not used)
assertIsomorphic(new Graph[] { graphsArray[0], graphsArray[1] },
true);
assertIsomorphic(new Graph[] { graphsArray[0], graphsArray[2] },
true);
assertIsomorphic(new Graph[] { graphsArray[1], graphsArray[2] },
true);
// create a functor according to odd even
EquivalenceComparator edgeEqChecker =
new DirectedEdgeWeightOddEvenComparator(graphsArray[0]);
assertIsomorphic(
new Graph[] { graphsArray[0], graphsArray[1] },
true,
null,
edgeEqChecker);
assertIsomorphic(
new Graph[] { graphsArray[0], graphsArray[2] },
false,
null,
edgeEqChecker);
assertIsomorphic(
new Graph[] { graphsArray[1], graphsArray[2] },
false,
null,
edgeEqChecker);
}
@SuppressWarnings("unchecked")
private void assertIsomorphicStopAfterFirstMatch(
Graph [] graphs,
boolean assertActive,
boolean shouldTheyBeIsomorphic,
EquivalenceComparator vertexChecker,
EquivalenceComparator edgeChecker)
{
if (assertActive) {
System.out.println("\nassertIsomorphic:"
+ shouldTheyBeIsomorphic);
}
Graph g1 = graphs[0];
Graph g2 = graphs[1];
System.out.println("g1:" + g1);
System.out.println("g2:" + g2);
long beforeTime = System.currentTimeMillis();
GraphIsomorphismInspector iso =
AdaptiveIsomorphismInspectorFactory.createIsomorphismInspector(
g1,
g2,
vertexChecker,
edgeChecker);
boolean isoResult = iso.isIsomorphic();
if (isoResult) {
System.out.println("Graphs are isomorphic. ");
} else {
System.out.println("Graphs are NOT isomorphic.");
}
long deltaTime = System.currentTimeMillis() - beforeTime;
String timeDesc;
timeDesc =
(deltaTime <= 10) ? "<10ms [less than minumun measurement time]"
: String.valueOf(deltaTime);
System.out.println(
"# Performence: Isomorphism check in MiliSeconds:" + timeDesc);
if (assertActive) {
assertEquals(shouldTheyBeIsomorphic, isoResult);
}
}
/**
* Performance test with different number of vertex, edges. For each number
* pair, 3 graphs are generated. The first two, using the same generator,
* the third using a different generator. Note: the 1st and 2nd must be
* isomorphic. The 3rd will most likely not be isomorphic , but on special
* occasaions may be, so do not assert it. (example: empty graph, full mesh
* , rare case that they are not real random). NOTE: RENAME TO testXXX to
* make it work. It shows output and not assertions, so it cannot be used by
* automatic tests.
*/
@SuppressWarnings("unchecked")
public void performanceTestOnRandomGraphs()
throws Exception
{
final int [] numOfVertexesArray =
new int[] {
6,
6,
6,
8,
8,
8,
10,
10,
10,
12,
14,
20,
30,
99
};
final int [] numOfEdgesArray =
new int[] {
0,
4,
12,
1,
15,
54,
0,
40,
90,
130,
50,
79,
30,
234
};
// there will be two different generators. The first will be used for
// 1st,2nd graph
// the other for the3rd graph
final int NUM_OF_GENERATORS = 2;
RandomGraphGenerator [] genArray =
new RandomGraphGenerator[NUM_OF_GENERATORS];
String [] graphConctereClassesFullName =
new String[] { // "org.jgrapht.graph.SimpleGraph" ,
"org.jgrapht.graph.SimpleDirectedGraph",
"org.jgrapht.graph.DefaultDirectedGraph",
// "org.jgrapht.graph.Multigraph",
// "org.jgrapht.graph.Pseudograph"
};
// 3 graphs. 1st,2nd must be isomorphic .3rd probably not iso.
final int SIZE_OF_GENERATED_GRAPH_ARRAY = 3;
// graphsArray rows are different graph types. Columns are few
// instances of that type
Graph [][] graphsArray =
new Graph[graphConctereClassesFullName.length][SIZE_OF_GENERATED_GRAPH_ARRAY];
Graph [] currIsoTestArray = new Graph[2];
for (int testNum = 0; testNum < numOfVertexesArray.length; testNum++) {
// recreate the graphs (empty)
try {
for (int i = 0; i < graphConctereClassesFullName.length; i++) {
for (int j = 0; j < SIZE_OF_GENERATED_GRAPH_ARRAY; j++) {
graphsArray[i][j] =
(Graph) Class.forName(
graphConctereClassesFullName[i]).newInstance();
}
}
} catch (Exception e) {
throw new Exception("failed to initilized the graphs", e);
}
// create generators for the new vertex/edges number
for (int i = 0; i < genArray.length; i++) {
genArray[i] =
new RandomGraphGenerator(
numOfVertexesArray[testNum],
numOfEdgesArray[testNum]);
}
for (
int graphType = 0;
graphType < graphConctereClassesFullName.length;
graphType++)
{
System.out.println(
"### numOfVertexes= " + numOfVertexesArray[testNum]);
System.out.println(
"### numOfEdges= " + numOfEdgesArray[testNum]);
System.out.println(
"######### Graph Type:"
+ graphConctereClassesFullName[graphType]);
System.out.println(
"# # # # # # # # # # # # # # # # # # # # # # # # # # # #");
// 1st and 2nd from genArray[0]
genArray[0].generateGraph(
graphsArray[graphType][0],
new IntegerVertexFactory(),
null);
genArray[0].generateGraph(
graphsArray[graphType][1],
new IntegerVertexFactory(),
null);
// 3rd from genArray[1]
genArray[1].generateGraph(
graphsArray[graphType][2],
new IntegerVertexFactory(),
null);
// now start testing
currIsoTestArray[0] = graphsArray[graphType][0];
currIsoTestArray[1] = graphsArray[graphType][1];
assertIsomorphicStopAfterFirstMatch(
currIsoTestArray,
true,
true,
null,
null);
// remember it is not a MUST - it can be true . DEGUG REASON
// ONLY , and with care
currIsoTestArray[1] = graphsArray[graphType][2];
assertIsomorphicStopAfterFirstMatch(
currIsoTestArray,
false,
false,
null,
null);
}
}
}
}
// End IsomorphismInspectorTest.java