/* $RCSfile$
* $Author$
* $Date$
* $Revision$
*
* Copyright (C) 2004-2009 Ulrich Bauer <ulrich.bauer@alumni.tum.de>
*
* Contact: cdk-devel@lists.sourceforge.net
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
* All we ask is that proper credit is given for our work, which includes
* - but is not limited to - adding the above copyright notice to the beginning
* of your source code files, and to any copyright notice that you may distribute
* with programs based on this work.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
package org.openscience.cdk.ringsearch.cyclebasis;
import org._3pq.jgrapht.DirectedGraph;
import org._3pq.jgrapht.Edge;
import org._3pq.jgrapht.Graph;
import org._3pq.jgrapht.UndirectedGraph;
import org._3pq.jgrapht.alg.ConnectivityInspector;
import org._3pq.jgrapht.graph.SimpleDirectedGraph;
import org._3pq.jgrapht.graph.SimpleGraph;
import org._3pq.jgrapht.graph.Subgraph;
import org.openscience.cdk.graph.BFSShortestPath;
import org.openscience.cdk.graph.MinimalPathIterator;
import java.util.*;
/**
* Auxiliary class for <code>CycleBasis</code>.
*
* @author Ulrich Bauer <ulrich.bauer@alumni.tum.de>
*
*
* @cdk.module standard
* @cdk.githash
*
* @cdk.builddepends jgrapht-0.5.3.jar
* @cdk.depends jgrapht-0.5.3.jar
*/
public class SimpleCycleBasis {
private List edgeList;
private List cycles;
private UndirectedGraph graph;
private boolean isMinimized = false;
private HashMap edgeIndexMap;
public SimpleCycleBasis (List cycles, List edgeList, UndirectedGraph graph) {
this.edgeList = edgeList;
this.cycles = cycles;
this.graph = graph;
edgeIndexMap = createEdgeIndexMap(edgeList);
}
public SimpleCycleBasis (UndirectedGraph graph) {
this.cycles = new ArrayList();
this.edgeList = new ArrayList();
this.graph = graph;
createMinimumCycleBasis();
}
private void createMinimumCycleBasis() {
Graph subgraph = new Subgraph(graph, null, null);
Set remainingEdges = new HashSet(graph.edgeSet());
Set selectedEdges = new HashSet();
while (!remainingEdges.isEmpty()) {
Edge edge = (Edge)remainingEdges.iterator().next();
subgraph.removeEdge(edge);
// Compute a shortest cycle through edge
List path = BFSShortestPath.findPathBetween(subgraph, edge.getSource(), edge.getTarget());
path.add(edge);
SimpleCycle cycle = new SimpleCycle(graph, path);
subgraph.addEdge(edge);
selectedEdges.add(edge);
cycles.add(0, cycle);
edgeList.add(0, edge);
remainingEdges.removeAll(path);
}
subgraph.removeAllEdges(selectedEdges);
// The cycles just created are already minimal, so we can start minimizing at startIndex
int startIndex = cycles.size();
// Now we perform a breadth first traversal and build a fundamental tree base
// ("Kirchhoff base") of the remaining subgraph
Object currentVertex = graph.vertexSet().iterator().next();
// We build a spanning tree as a directed graph to easily find the parent of a
// vertex in the tree. This means however that we have to create new Edge objects
// for the tree and can't just use the Edge objects of the graph, since the
// the edge in the graph might have a wrong or no direction.
Graph spanningTree = new Subgraph(graph, new HashSet(), new HashSet());
Set visitedEdges = new HashSet();
// FIFO for the BFS
LinkedList vertexQueue = new LinkedList();
// currentVertex is the root of the spanning tree
spanningTree.addVertex(currentVertex);
vertexQueue.addLast(currentVertex);
// We need to remember the tree edges so we can add them at once to the
// index list for the incidence matrix
List treeEdges = new Vector();
while (!vertexQueue.isEmpty()) {
currentVertex = vertexQueue.removeFirst();
Iterator edges = subgraph.edgesOf(currentVertex).iterator();
while (edges.hasNext()) {
// find a neighbour vertex of the current vertex
Edge edge = (Edge)edges.next();
if (!visitedEdges.contains(edge)) {
// mark edge as visited
visitedEdges.add(edge);
Object nextVertex = edge.oppositeVertex(currentVertex);
if (!spanningTree.containsVertex(nextVertex)) {
// tree edge
treeEdges.add(edge);
spanningTree.addVertex(nextVertex);
// create a new (directed) Edge object (as explained above)
spanningTree.addEdge(currentVertex, nextVertex);
// add the next vertex to the BFS-FIFO
vertexQueue.addLast(nextVertex);
} else {
// non-tree edge
// This edge defines a cycle together with the edges of the spanning tree
// along the path to the root of the tree. We create a new cycle containing
// these edges (not the tree edges, but the corresponding edges in the graph)
List edgesOfCycle = BFSShortestPath.findPathBetween(spanningTree, edge.getSource(), edge.getTarget());
// add the non-tree edge to the path
edgesOfCycle.add(edge);
// add the edge to the index list for the incidence matrix
edgeList.add(edge);
SimpleCycle newCycle = new SimpleCycle(graph, edgesOfCycle);
cycles.add(newCycle);
}
}
}
}
// Add all the tree edges to the index list for the incidence matrix
edgeList.addAll(treeEdges);
edgeIndexMap = createEdgeIndexMap(edgeList);
// Now the index list is ordered: first the non-tree edges, then the tree edge.
// Moreover, since the cycles and the corresponding non-tree edge have been added
// to their lists in the same order, the incidence matrix is in upper triangular form.
// Now we can minimize the cycles created from the tree base
minimize(startIndex);
}
boolean[][] getCycleEdgeIncidenceMatrix () {
return getCycleEdgeIncidenceMatrix((Object[]) cycles.toArray());
}
boolean[][] getCycleEdgeIncidenceMatrix (Object[] cycleArray) {
boolean[][] result = new boolean[cycleArray.length][edgeList.size()];
for (int i=0; i<cycleArray.length; i++) {
SimpleCycle cycle = (SimpleCycle) cycleArray[i];
for (int j=0; j<edgeList.size(); j++) {
Edge edge = (Edge)edgeList.get(j);
result[i][j] = cycle.containsEdge(edge);
}
}
return result;
}
// private void minimize() {
//
// if (isMinimized)
// return;
//
// if (cycles.size()==0)
// return;
// else
// minimize(0);
//
// isMinimized = true;
// }
private void minimize(int startIndex) {
if (isMinimized)
return;
// Implementation of "Algorithm 1" from [BGdV04]
boolean[][] a = getCycleEdgeIncidenceMatrix();
for (int i=startIndex; i<cycles.size(); i++) {
// "Subroutine 2"
// Construct kernel vector u
boolean[] u = constructKernelVector(edgeList.size(), a, i);
// Construct auxiliary graph gu
AuxiliaryGraph gu = new AuxiliaryGraph(graph, u);
SimpleCycle shortestCycle = (SimpleCycle) cycles.get(i);
Iterator vertexIterator = graph.vertexSet().iterator();
while (vertexIterator.hasNext()) {
Object vertex = vertexIterator.next();
// check if the vertex is incident to an edge with u[edge] == 1
boolean shouldSearchCycle = false;
Collection incidentEdges = graph.edgesOf(vertex);
Iterator edgeIterator = incidentEdges.iterator();
while (edgeIterator.hasNext()) {
Edge edge = (Edge) edgeIterator.next();
int index = getEdgeIndex(edge);
if (u[index]) {
shouldSearchCycle = true;
break;
}
}
if (shouldSearchCycle) {
Object auxVertex0 = gu.auxVertex0(vertex);
Object auxVertex1 = gu.auxVertex1(vertex);
// Search for shortest path
List auxPath = BFSShortestPath.findPathBetween(gu, auxVertex0, auxVertex1);
List edgesOfNewCycle = new Vector();
Object v = vertex;
edgeIterator = auxPath.iterator();
while (edgeIterator.hasNext()) {
Edge auxEdge = (Edge) edgeIterator.next();
// Get the edge corresponding to the aux. edge
Edge e = (Edge) gu.edge(auxEdge);
if (edgesOfNewCycle.contains(e)) {
edgesOfNewCycle.remove(e);
} else {
edgesOfNewCycle.add(e);
}
// Get next vertex on path
v = e.oppositeVertex(v);
}
SimpleCycle newCycle = new SimpleCycle(graph, edgesOfNewCycle);
if (newCycle.weight() < shortestCycle.weight()) {
shortestCycle = newCycle;
}
}
}
cycles.set(i, shortestCycle);
// insert the new cycle into the matrix
for (int j=0; j<edgeList.size(); j++) {
a[i][j] = shortestCycle.containsEdge((Edge) edgeList.get(j));
}
// perform gaussian elimination on the inserted row
for (int j=0; j<i; j++) {
if (a[i][j]) {
for (int k=0; k<edgeList.size(); k++) {
a[i][k] = (a[i][k]!=a[j][k]);
}
}
}
}
isMinimized = true;
//System.out.println("after minimization:");
//printIncidenceMatrix();
}
static boolean[] constructKernelVector(int size, boolean[][] a, int i) {
// Construct kernel vector u by setting u[i] = true ...
boolean[] u = new boolean[size];
u[i] = true;
// ... u[j] = 0 (false) for j > i (by initialization)...
// ... and solving A u = 0
for (int j=i-1; j>=0; j--) {
u[j] = false;
for (int k=i; k>j; k--) {
u[j] = (u[j] != (a[j][k] && u[k]));
}
}
return u;
}
public int[] weightVector() {
int[] result = new int[cycles.size()];
for (int i=0; i<cycles.size(); i++) {
SimpleCycle cycle = (SimpleCycle) cycles.get(i);
result[i] = (int) cycle.weight();
}
Arrays.sort(result);
return result;
}
public List edges() {
return edgeList;
}
public List cycles() {
return cycles;
}
static boolean[][] inverseBinaryMatrix(boolean[][] m, int n) {
boolean[][] a = new boolean[n][n];
for (int i=0; i<n; i++) {
for (int j=0; j<n; j++) {
a[i][j] = m[i][j];
}
}
boolean[][] r = new boolean[n][n];
for (int i=0; i<n; i++) {
r[i][i] = true;
}
for (int i=0; i<n; i++) {
for (int j=i; j<n; j++) {
if (a[j][i]) {
for (int k=0; k<n; k++) {
if ((k!=j) && (a[k][i])) {
for (int l=0; l<n; l++) {
a[k][l] = (a[k][l] != a[j][l]);
r[k][l] = (r[k][l] != r[j][l]);
}
}
}
if (i!=j) {
boolean[] swap = a[i];
a[i] = a[j];
a[j] = swap;
swap = r[i];
r[i] = r[j];
r[j] = swap;
}
break;
}
}
}
return r;
}
public Collection essentialCycles() {
Collection result = new HashSet();
boolean[][] a = getCycleEdgeIncidenceMatrix();
boolean[][] ai = inverseBinaryMatrix(a, cycles.size());
for (int i=0; i<cycles.size(); i++) {
// Construct kernel vector u
boolean[] u = new boolean[edgeList.size()];
for (int j=0; j<cycles.size(); j++) {
u[j] = ai[j][i];
}
// Construct kernel vector u from a column of the inverse of a
AuxiliaryGraph gu = new AuxiliaryGraph(graph, u);
boolean isEssential = true;
Iterator vertexIterator = graph.vertexSet().iterator();
while (isEssential && vertexIterator.hasNext()) {
Object vertex = vertexIterator.next();
Collection incidentEdges = graph.edgesOf(vertex);
// check if the vertex is incident to an edge with u[edge] == 1
boolean shouldSearchCycle = false;
for (Iterator it = incidentEdges.iterator(); it.hasNext();) {
Edge edge = (Edge) it.next();
int index = getEdgeIndex(edge);
if (u[index]) {
shouldSearchCycle = true;
break;
}
}
if (shouldSearchCycle) {
Object auxVertex0 = gu.auxVertex0(vertex);
Object auxVertex1 = gu.auxVertex1(vertex);
// Search for shortest paths
for (Iterator minPaths = new MinimalPathIterator(gu, auxVertex0, auxVertex1); minPaths.hasNext();) {
List auxPath = (List) minPaths.next();
List edgesOfNewCycle = new ArrayList(auxPath.size());
for (Iterator it = auxPath.iterator(); it.hasNext();) {
Edge auxEdge = (Edge) it.next();
// Get the edge corresponding to the aux. edge
Edge e = (Edge) gu.edge(auxEdge);
if (edgesOfNewCycle.contains(e)) {
edgesOfNewCycle.remove(e);
} else {
edgesOfNewCycle.add(e);
}
}
SimpleCycle cycle = new SimpleCycle(graph, edgesOfNewCycle);
if (cycle.weight() > ((SimpleCycle)cycles.get(i)).weight()) {
break;
}
if (!cycle.equals((SimpleCycle)cycles.get(i))) {
isEssential = false;
break;
}
}
}
}
if (isEssential) {
result.add((SimpleCycle)cycles.get(i));
}
}
return result;
}
public Map relevantCycles() {
Map result = new HashMap();
boolean[][] a = getCycleEdgeIncidenceMatrix();
boolean[][] ai = inverseBinaryMatrix(a, cycles.size());
for (int i=0; i<cycles.size(); i++) {
// Construct kernel vector u from a column of the inverse of a
boolean[] u = new boolean[edgeList.size()];
for (int j=0; j<cycles.size(); j++) {
u[j] = ai[j][i];
}
// Construct auxiliary graph gu
AuxiliaryGraph gu = new AuxiliaryGraph(graph, u);
Iterator vertexIterator = graph.vertexSet().iterator();
while (vertexIterator.hasNext()) {
Object vertex = vertexIterator.next();
Collection incidentEdges = graph.edgesOf(vertex);
// check if the vertex is incident to an edge with u[edge] == 1
boolean shouldSearchCycle = false;
for (Iterator it = incidentEdges.iterator(); it.hasNext();) {
Edge edge = (Edge) it.next();
int index = getEdgeIndex(edge);
if (u[index]) {
shouldSearchCycle = true;
break;
}
}
if (shouldSearchCycle) {
Object auxVertex0 = gu.auxVertex0(vertex);
Object auxVertex1 = gu.auxVertex1(vertex);
// Search for shortest paths
for (Iterator minPaths = new MinimalPathIterator(gu, auxVertex0, auxVertex1); minPaths.hasNext();) {
List auxPath = (List) minPaths.next();
List edgesOfNewCycle = new ArrayList(auxPath.size());
Iterator edgeIterator = auxPath.iterator();
while (edgeIterator.hasNext()) {
Edge auxEdge = (Edge) edgeIterator.next();
// Get the edge corresponding to the aux. edge
Edge e = (Edge) gu.edge(auxEdge);
if (edgesOfNewCycle.contains(e)) {
edgesOfNewCycle.remove(e);
} else {
edgesOfNewCycle.add(e);
}
}
SimpleCycle cycle = new SimpleCycle(graph, edgesOfNewCycle);
if (cycle.weight() > ((SimpleCycle)cycles.get(i)).weight()) {
break;
}
result.put(cycle, (SimpleCycle)cycles.get(i));
}
}
}
}
return result;
}
public List equivalenceClasses() {
int[] weight = weightVector();
Object[] cyclesArray = (Object[]) cycles.toArray();
Arrays.sort(cyclesArray, new Comparator() {
public int compare(Object o1, Object o2) {
return (int) (((SimpleCycle)o1).weight() - ((SimpleCycle)o2).weight());
}
});
Collection essentialCycles = essentialCycles();
boolean[][] u = new boolean[cyclesArray.length][edgeList.size()];
boolean[][] a = getCycleEdgeIncidenceMatrix(cyclesArray);
boolean[][] ai = inverseBinaryMatrix(a, cyclesArray.length);
for (int i=0; i<cyclesArray.length; i++) {
for (int j=0; j<cyclesArray.length; j++) {
u[i][j] = ai[j][i];
}
}
UndirectedGraph h = new SimpleGraph();
h.addAllVertices(cycles);
ConnectivityInspector connectivityInspector = new ConnectivityInspector(h);
int left=0;
for (int right=0; right<weight.length; right++) {
if ((right<weight.length-1) && (weight[right+1]==weight[right]))
continue;
// cyclesArray[left] to cyclesArray[right] have same weight
// First test (compute pre-classes):
// Check if there is a cycle that can replace a[i] as well as a[j] in a basis
// This is done by finding a cycle C with <C,u[i]>=1 and <C,u[j]>=1
for (int i=left; i<=right; i++) {
if (essentialCycles.contains((SimpleCycle) cyclesArray[i]))
continue;
for (int j=i+1; j<=right; j++) {
if (essentialCycles.contains((SimpleCycle) cyclesArray[j]))
continue;
// check if cyclesArray[i] and cyclesArray[j] are already in the same class
if (connectivityInspector.pathExists(cyclesArray[i], cyclesArray[j]))
continue;
boolean sameClass = false;
AuxiliaryGraph2 auxGraph = new AuxiliaryGraph2(graph, edgeList, u[i], u[j]);
for (Iterator it = graph.vertexSet().iterator(); it.hasNext();) {
Object vertex = it.next();
// check if the vertex is incident to an edge with u[edge] == 1
boolean shouldSearchCycle = false;
Collection incidentEdges = graph.edgesOf(vertex);
Iterator edgeIterator = incidentEdges.iterator();
while (edgeIterator.hasNext()) {
Edge edge = (Edge) edgeIterator.next();
int index = getEdgeIndex(edge);
if (u[i][index] || u[j][index]) {
shouldSearchCycle = true;
break;
}
}
if (shouldSearchCycle) {
Object auxVertex00 = auxGraph.auxVertex00(vertex);
Object auxVertex11 = auxGraph.auxVertex11(vertex);
List auxPath = BFSShortestPath.findPathBetween(auxGraph, auxVertex00, auxVertex11);
double pathWeight = auxPath.size();
if (pathWeight == weight[left]) {
sameClass = true;
break;
}
}
}
if (sameClass) {
h.addEdge(cyclesArray[i], cyclesArray[j]);
}
}
}
// Second test (compute equivalence classes):
// Check if there are two cycle Ci, Cj that can replace a[i], a[j]
// and have a common cycle a[k] in their basis representation
// This is done by finding a cycle a[k] with <u[k],u[i]>=1 and <u[k],u[j]>=1
for (int i=left; i<=right; i++) {
if (essentialCycles.contains((SimpleCycle) cyclesArray[i]))
continue;
for (int j=i+1; j<=right; j++) {
if (essentialCycles.contains((SimpleCycle) cyclesArray[j]))
continue;
// check if cyclesArray[i] and cyclesArray[j] are already in the same class
if (connectivityInspector.pathExists(cyclesArray[i], cyclesArray[j]))
continue;
boolean sameClass = false;
for (int k=0; ((SimpleCycle)cyclesArray[k]).weight() < weight[left]; k++) {
AuxiliaryGraph2 auxGraph = new AuxiliaryGraph2(graph, edgeList, u[i], u[k]);
boolean shortestPathFound = false;
for (Iterator it = graph.vertexSet().iterator(); it.hasNext();) {
Object vertex = it.next();
Object auxVertex00 = auxGraph.auxVertex00(vertex);
Object auxVertex11 = auxGraph.auxVertex11(vertex);
List auxPath = BFSShortestPath.findPathBetween(auxGraph, auxVertex00, auxVertex11);
double pathWeight = auxPath.size();
if (pathWeight == weight[left]) {
shortestPathFound = true;
break;
}
}
if (!shortestPathFound)
continue;
auxGraph = new AuxiliaryGraph2(graph, edgeList, u[j], u[k]);
for (Iterator it = graph.vertexSet().iterator(); it.hasNext();) {
Object vertex = it.next();
Object auxVertex00 = auxGraph.auxVertex00(vertex);
Object auxVertex11 = auxGraph.auxVertex11(vertex);
List auxPath = BFSShortestPath.findPathBetween(auxGraph, auxVertex00, auxVertex11);
double pathWeight = auxPath.size();
if (pathWeight == weight[left]) {
sameClass = true;
break;
}
}
if (sameClass)
break;
}
if (sameClass) {
h.addEdge(cyclesArray[i], cyclesArray[j]);
}
}
}
left=right+1;
}
return connectivityInspector.connectedSets();
}
private HashMap createEdgeIndexMap(List edgeList) {
HashMap map = new HashMap();
for (int i=0; i<edgeList.size(); i++) {
map.put(edgeList.get(i), Integer.valueOf(i));
}
return map;
}
private int getEdgeIndex(Edge edge) {
return ((Integer) edgeIndexMap.get(edge)).intValue();
}
private class AuxiliaryGraph extends SimpleGraph {
private static final long serialVersionUID = 857337988734567429L;
// graph to aux. graph
HashMap vertexMap0 = new HashMap();
HashMap vertexMap1 = new HashMap();
HashMap auxVertexMap = new HashMap();
// aux. edge to edge
Map auxEdgeMap = new HashMap();
Graph g;
boolean[] u;
AuxiliaryGraph(Graph graph, boolean[] u) {
g = graph;
this.u = u;
}
public List edgesOf( Object auxVertex ) {
Object vertex = auxVertexMap.get(auxVertex);
for (Iterator edgeIterator = g.edgesOf(vertex).iterator(); edgeIterator.hasNext();) {
Edge edge = (Edge) edgeIterator.next();
int j = getEdgeIndex(edge);
Object vertex1 = edge.getSource();
Object vertex2 = edge.getTarget();
if (u[j]) {
Object vertex1u = auxVertex0(vertex1);
Object vertex2u = auxVertex1(vertex2);
Edge auxEdge = addEdge(vertex1u, vertex2u);
auxEdgeMap.put(auxEdge, edge);
vertex1u = auxVertex1(vertex1);
vertex2u = auxVertex0(vertex2);
auxEdge = addEdge(vertex1u, vertex2u);
auxEdgeMap.put(auxEdge, edge);
} else {
Object vertex1u = auxVertex0(vertex1);
Object vertex2u = auxVertex0(vertex2);
Edge auxEdge = addEdge(vertex1u, vertex2u);
auxEdgeMap.put(auxEdge, edge);
vertex1u = auxVertex1(vertex1);
vertex2u = auxVertex1(vertex2);
auxEdge = addEdge(vertex1u, vertex2u);
auxEdgeMap.put(auxEdge, edge);
}
}
return super.edgesOf(auxVertex);
}
Object auxVertex0(Object vertex) {
if (vertexMap0.get(vertex) == null) {
Object newVertex0 = vertex + "-0";
vertexMap0.put(vertex, newVertex0);
addVertex(newVertex0);
auxVertexMap.put(newVertex0, vertex);
return newVertex0;
}
return vertexMap0.get(vertex);
}
Object auxVertex1(Object vertex) {
if (vertexMap1.get(vertex) == null) {
Object newVertex1 = vertex + "-1";
vertexMap1.put(vertex, newVertex1);
addVertex(newVertex1);
auxVertexMap.put(newVertex1, vertex);
return newVertex1;
}
return vertexMap1.get(vertex);
}
Object edge(Object auxEdge) {
return auxEdgeMap.get(auxEdge);
}
}
private class AuxiliaryGraph2 extends SimpleGraph {
private static final long serialVersionUID = 5930876716644738726L;
// graph to aux. graph
private HashMap vertexMap00 = new HashMap();
private HashMap vertexMap01 = new HashMap();
private HashMap vertexMap10 = new HashMap();
private HashMap vertexMap11 = new HashMap();
private HashMap auxVertexMap = new HashMap();
// aux. edge to edge
private Map auxEdgeMap = new HashMap();
private Graph g;
private boolean[] ui;
private boolean[] uj;
AuxiliaryGraph2(Graph graph, List edgeList, boolean[] ui, boolean[] uj) {
g = graph;
this.ui = ui;
this.uj = uj;
}
Object auxVertex00(Object vertex) {
if (vertexMap00.get(vertex) == null) {
Object newVertex = vertex + "-00";
vertexMap00.put(vertex, newVertex);
addVertex(newVertex);
auxVertexMap.put(newVertex, vertex);
return newVertex;
}
return vertexMap00.get(vertex);
}
Object auxVertex01(Object vertex) {
if (vertexMap01.get(vertex) == null) {
Object newVertex = vertex + "-01";
vertexMap01.put(vertex, newVertex);
addVertex(newVertex);
auxVertexMap.put(newVertex, vertex);
return newVertex;
}
return vertexMap01.get(vertex);
}
Object auxVertex10(Object vertex) {
if (vertexMap10.get(vertex) == null) {
Object newVertex = vertex + "-10";
vertexMap10.put(vertex, newVertex);
addVertex(newVertex);
auxVertexMap.put(newVertex, vertex);
return newVertex;
}
return vertexMap10.get(vertex);
}
Object auxVertex11(Object vertex) {
if (vertexMap11.get(vertex) == null) {
Object newVertex = vertex + "-11";
vertexMap11.put(vertex, newVertex);
addVertex(newVertex);
auxVertexMap.put(newVertex, vertex);
return newVertex;
}
return vertexMap11.get(vertex);
}
public List edgesOf( Object auxVertex ) {
Object vertex = auxVertexMap.get(auxVertex);
for (Iterator edgeIterator = g.edgesOf(vertex).iterator(); edgeIterator.hasNext();) {
Edge edge = (Edge) edgeIterator.next();
int k = getEdgeIndex(edge);
Object vertex1 = edge.getSource();
Object vertex2 = edge.getTarget();
if (!ui[k] && !uj[k]) {
Object vertex1u = auxVertex00(vertex1);
Object vertex2u = auxVertex00(vertex2);
Edge auxEdge = addEdge(vertex1u, vertex2u);
auxEdgeMap.put(auxEdge, edge);
vertex1u = auxVertex01(vertex1);
vertex2u = auxVertex01(vertex2);
auxEdge = addEdge(vertex1u, vertex2u);
auxEdgeMap.put(auxEdge, edge);
vertex1u = auxVertex10(vertex1);
vertex2u = auxVertex10(vertex2);
auxEdge = addEdge(vertex1u, vertex2u);
auxEdgeMap.put(auxEdge, edge);
vertex1u = auxVertex11(vertex1);
vertex2u = auxVertex11(vertex2);
auxEdge = addEdge(vertex1u, vertex2u);
auxEdgeMap.put(auxEdge, edge);
} else if (ui[k] && !uj[k]) {
Object vertex1u = auxVertex00(vertex1);
Object vertex2u = auxVertex10(vertex2);
Edge auxEdge = addEdge(vertex1u, vertex2u);
auxEdgeMap.put(auxEdge, edge);
vertex1u = auxVertex01(vertex1);
vertex2u = auxVertex11(vertex2);
auxEdge = addEdge(vertex1u, vertex2u);
auxEdgeMap.put(auxEdge, edge);
vertex1u = auxVertex10(vertex1);
vertex2u = auxVertex00(vertex2);
auxEdge = addEdge(vertex1u, vertex2u);
auxEdgeMap.put(auxEdge, edge);
vertex1u = auxVertex11(vertex1);
vertex2u = auxVertex01(vertex2);
auxEdge = addEdge(vertex1u, vertex2u);
auxEdgeMap.put(auxEdge, edge);
} else if (!ui[k] && uj[k]) {
Object vertex1u = auxVertex00(vertex1);
Object vertex2u = auxVertex01(vertex2);
Edge auxEdge = addEdge(vertex1u, vertex2u);
auxEdgeMap.put(auxEdge, edge);
vertex1u = auxVertex01(vertex1);
vertex2u = auxVertex00(vertex2);
auxEdge = addEdge(vertex1u, vertex2u);
auxEdgeMap.put(auxEdge, edge);
vertex1u = auxVertex10(vertex1);
vertex2u = auxVertex11(vertex2);
auxEdge = addEdge(vertex1u, vertex2u);
auxEdgeMap.put(auxEdge, edge);
vertex1u = auxVertex11(vertex1);
vertex2u = auxVertex10(vertex2);
auxEdge = addEdge(vertex1u, vertex2u);
auxEdgeMap.put(auxEdge, edge);
} else if (ui[k] && uj[k]) {
Object vertex1u = auxVertex00(vertex1);
Object vertex2u = auxVertex11(vertex2);
Edge auxEdge = addEdge(vertex1u, vertex2u);
auxEdgeMap.put(auxEdge, edge);
vertex1u = auxVertex01(vertex1);
vertex2u = auxVertex10(vertex2);
auxEdge = addEdge(vertex1u, vertex2u);
auxEdgeMap.put(auxEdge, edge);
vertex1u = auxVertex10(vertex1);
vertex2u = auxVertex01(vertex2);
auxEdge = addEdge(vertex1u, vertex2u);
auxEdgeMap.put(auxEdge, edge);
vertex1u = auxVertex11(vertex1);
vertex2u = auxVertex00(vertex2);
auxEdge = addEdge(vertex1u, vertex2u);
auxEdgeMap.put(auxEdge, edge);
}
}
return super.edgesOf(auxVertex);
}
}
public void printIncidenceMatrix() {
/*
for (int j=0; j<edgeList.size(); j++) {
System.out.print(((Edge) edgeList.get(j)).getSource());
}
System.out.println();
for (int j=0; j<edgeList.size(); j++) {
System.out.print(((Edge) edgeList.get(j)).getTarget());
}
System.out.println();
for (int j=0; j<edgeList.size(); j++) {
System.out.print('-');
}
System.out.println();
*/
boolean[][] incidMatr = getCycleEdgeIncidenceMatrix();
for (int i=0; i<incidMatr.length; i++) {
for (int j=0; j<incidMatr[i].length; j++) {
System.out.print(incidMatr[i][j]?1:0);
}
System.out.println();
}
}
}