org.jgrapht.io.MatrixExporter Maven / Gradle / Ivy
/*
* (C) Copyright 2005-2017, by Charles Fry, Dimitrios Michail and Contributors.
*
* JGraphT : a free Java graph-theory library
*
* 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.
*/
package org.jgrapht.io;
import java.io.*;
import java.util.*;
import org.jgrapht.*;
import org.jgrapht.util.*;
/**
* Exports a graph to a plain text matrix format, which can be processed by matrix manipulation
* software, such as MTJ or
* MATLAB.
*
*
* The exporter supports three different formats, see {@link Format}.
*
*
* @see Format
*
* @param the graph vertex type
* @param the graph edge type
*
* @author Charles Fry
* @author Dimitrios Michail
*/
public class MatrixExporter
extends AbstractBaseExporter
implements GraphExporter
{
private final String delimiter = " ";
private Format format;
/**
* Formats supported by the {@link MatrixExporter} exporter.
*/
public enum Format
{
/**
* A sparse representation of the adjacency matrix. This is the default. Exports the
* specified graph into a plain text file format containing a sparse representation of the
* graph's adjacency matrix. The value stored in each position of the matrix indicates the
* number of edges between two vertices. With an undirected graph, the adjacency matrix is
* symmetric.
*/
SPARSE_ADJACENCY_MATRIX,
/**
* A sparse representation of the Laplacian.
*/
SPARSE_LAPLACIAN_MATRIX,
/**
* A sparse representation of the normalized Laplacian.
*/
SPARSE_NORMALIZED_LAPLACIAN_MATRIX,
}
/**
* Creates a new MatrixExporter with integer name provider for the vertex identifiers and
* {@link Format#SPARSE_ADJACENCY_MATRIX} as the default format.
*/
public MatrixExporter()
{
this(Format.SPARSE_ADJACENCY_MATRIX, new IntegerComponentNameProvider<>());
}
/**
* Creates a new MatrixExporter with integer name provider for the vertex identifiers.
*
* @param format format to use
*/
public MatrixExporter(Format format)
{
this(format, new IntegerComponentNameProvider<>());
}
/**
* Creates a new MatrixExporter.
*
* @param format format to use
* @param vertexIDProvider for generating vertex identifiers. Must not be null.
*/
public MatrixExporter(Format format, ComponentNameProvider vertexIDProvider)
{
super(vertexIDProvider);
this.format = format;
}
/**
* Get the format that the exporter is using.
*
* @return the output format
*/
public Format getFormat()
{
return format;
}
/**
* Set the output format of the exporter
*
* @param format the format to use
*/
public void setFormat(Format format)
{
this.format = format;
}
@Override
public void exportGraph(Graph g, Writer writer)
throws ExportException
{
switch (format) {
case SPARSE_ADJACENCY_MATRIX:
exportAdjacencyMatrix(g, writer);
break;
case SPARSE_LAPLACIAN_MATRIX:
if (g.getType().isUndirected()) {
exportLaplacianMatrix(g, writer);
} else {
throw new ExportException(
"Exporter can only export undirected graphs in this format");
}
break;
case SPARSE_NORMALIZED_LAPLACIAN_MATRIX:
if (g.getType().isUndirected()) {
exportNormalizedLaplacianMatrix(g, writer);
} else {
throw new ExportException(
"Exporter can only export undirected graphs in this format");
}
break;
}
}
private void exportAdjacencyMatrix(Graph g, Writer writer)
{
for (V from : g.vertexSet()) {
// assign ids in vertex set iteration order
vertexIDProvider.getName(from);
}
PrintWriter out = new PrintWriter(writer);
if (g.getType().isDirected()) {
for (V from : g.vertexSet()) {
exportAdjacencyMatrixVertex(out, from, Graphs.successorListOf(g, from));
}
} else {
for (V from : g.vertexSet()) {
exportAdjacencyMatrixVertex(out, from, Graphs.neighborListOf(g, from));
}
}
out.flush();
}
private void exportAdjacencyMatrixVertex(PrintWriter writer, V from, List neighbors)
{
String fromName = vertexIDProvider.getName(from);
Map counts = new LinkedHashMap<>();
for (V to : neighbors) {
String toName = vertexIDProvider.getName(to);
ModifiableInteger count = counts.get(toName);
if (count == null) {
count = new ModifiableInteger(0);
counts.put(toName, count);
}
count.increment();
if (from.equals(to)) {
// count loops twice, once for each end
count.increment();
}
}
for (Map.Entry entry : counts.entrySet()) {
String toName = entry.getKey();
ModifiableInteger count = entry.getValue();
exportEntry(writer, fromName, toName, count.toString());
}
}
private void exportEntry(PrintWriter writer, String from, String to, String value)
{
writer.println(from + delimiter + to + delimiter + value);
}
private void exportLaplacianMatrix(Graph g, Writer writer)
{
PrintWriter out = new PrintWriter(writer);
ComponentNameProvider nameProvider = new IntegerComponentNameProvider<>();
for (V from : g.vertexSet()) {
// assign ids in vertex set iteration order
nameProvider.getName(from);
}
for (V from : g.vertexSet()) {
String fromName = nameProvider.getName(from);
List neighbors = Graphs.neighborListOf(g, from);
exportEntry(out, fromName, fromName, Integer.toString(neighbors.size()));
for (V to : neighbors) {
String toName = nameProvider.getName(to);
exportEntry(out, fromName, toName, "-1");
}
}
out.flush();
}
private void exportNormalizedLaplacianMatrix(Graph g, Writer writer)
{
PrintWriter out = new PrintWriter(writer);
ComponentNameProvider nameProvider = new IntegerComponentNameProvider<>();
for (V from : g.vertexSet()) {
// assign ids in vertex set iteration order
nameProvider.getName(from);
}
for (V from : g.vertexSet()) {
String fromName = nameProvider.getName(from);
Set neighbors = new LinkedHashSet<>(Graphs.neighborListOf(g, from));
if (neighbors.isEmpty()) {
exportEntry(out, fromName, fromName, "0");
} else {
exportEntry(out, fromName, fromName, "1");
for (V to : neighbors) {
String toName = nameProvider.getName(to);
double value = -1 / Math.sqrt(g.degreeOf(from) * g.degreeOf(to));
exportEntry(out, fromName, toName, Double.toString(value));
}
}
}
out.flush();
}
}
// End MatrixExporter.java