Java tutorial
/* * Copyright (c) 2003, the JUNG Project and the Regents of the University * of California * All rights reserved. * * This software is open-source under the BSD license; see either * "license.txt" or * http://jung.sourceforge.net/license.txt for a description. */ /* * Created on Jan 6, 2002 * */ package edu.uci.ics.jung.io; import cern.colt.matrix.DoubleMatrix2D; import cern.colt.matrix.impl.SparseDoubleMatrix2D; import edu.uci.ics.jung.algorithms.matrix.GraphMatrixOperations; import edu.uci.ics.jung.graph.Graph; import org.apache.commons.collections15.Factory; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.StringTokenizer; /** * Basic I/O handler for ascii matrix files. An ascii matrix is simply * a square matrix where 0 values for cell (i,j) indicates no edge exists between * vertex i and vertex j and non-zero values indicates there is an edge. If * a non-null weight key is specified then it will be used to treat the non-zero * values as a weight stored in the edges' user data keyed off the specified weight key value. * <p> * When loading a graph from a file, a symmetric graph will result in the construction of * an undirected sparse graph while a non-symmetric graph will result in the construction of * a directed sparse graph. * <p> * For example the following ascii matrix when loaded using the code:<br><code> * MatrixFile mf = new MatrixFile(null); <br> * Graph g = mf.load(filename); </code><br> * will produce an undirected sparse matrix with no weights: <br> * <pre> * 0 1 0 1 * 1 0 0 1 * 0 0 0 0 * 1 1 0 0 * </pre><p> * whereas the following ascii matrix when loaded using the code:<br><code> * MatrixFile mf = new MatrixFile("WEIGHT"); <br> * Graph g = mf.load(filename); </code> <br> * will produce a directed sparse matrix with double weight values stored in * the edges user data under the key "WEIGHT" : <br> * <pre> * 0 .5 10 0 * 0 1 0 0 * 0 0 0 -30 * 5 0 0 0 * </pre> * @author Scott * @author Tom Nelson - converted to jung2 * */ public class MatrixFile<V, E> implements GraphFile<V, E> { private Map<E, Number> mWeightKey; Factory<? extends Graph<V, E>> graphFactory; Factory<V> vertexFactory; Factory<E> edgeFactory; /** * Constructs MatrixFile instance. If weightKey is not null then, it will * attempt to use that key to store and retreive weights from the edges' * UserData. */ public MatrixFile(Map<E, Number> weightKey, Factory<? extends Graph<V, E>> graphFactory, Factory<V> vertexFactory, Factory<E> edgeFactory) { mWeightKey = weightKey; this.graphFactory = graphFactory; this.vertexFactory = vertexFactory; this.edgeFactory = edgeFactory; } /** * Loads a graph from an input reader * @param reader the input reader * @return the graph * @throws IOException */ public Graph<V, E> load(BufferedReader reader) throws IOException { Graph<V, E> graph = null; DoubleMatrix2D matrix = createMatrixFromFile(reader); graph = GraphMatrixOperations.<V, E>matrixToGraph(matrix, graphFactory, vertexFactory, edgeFactory); return graph; } private DoubleMatrix2D createMatrixFromFile(BufferedReader reader) throws IOException { List<List<Double>> rows = new ArrayList<List<Double>>(); String currentLine = null; while ((currentLine = reader.readLine()) != null) { StringTokenizer tokenizer = new StringTokenizer(currentLine); if (tokenizer.countTokens() == 0) { break; } List<Double> currentRow = new ArrayList<Double>(); while (tokenizer.hasMoreTokens()) { String token = tokenizer.nextToken(); currentRow.add(Double.parseDouble(token)); } rows.add(currentRow); } int size = rows.size(); DoubleMatrix2D matrix = new SparseDoubleMatrix2D(size, size); for (int i = 0; i < size; i++) { List<Double> currentRow = rows.get(i); if (currentRow.size() != size) { throw new IllegalArgumentException("Matrix must have the same number of rows as columns"); } for (int j = 0; j < size; j++) { double currentVal = currentRow.get(j); if (currentVal != 0) { matrix.setQuick(i, j, currentVal); } } } return matrix; } /** * Loads a graph from a file. * @see edu.uci.ics.jung.io.GraphFile#load(java.lang.String) */ public Graph<V, E> load(String filename) { try { BufferedReader reader = new BufferedReader(new FileReader(filename)); Graph<V, E> graph = load(reader); reader.close(); return graph; } catch (IOException ioe) { throw new RuntimeException("Error in loading file " + filename, ioe); } } /** * Saves a graph to a file * @see edu.uci.ics.jung.io.GraphFile#save(edu.uci.ics.jung.graph.Graph, java.lang.String) */ public void save(Graph<V, E> graph, String filename) { try { BufferedWriter writer = new BufferedWriter(new FileWriter(filename)); DoubleMatrix2D matrix = GraphMatrixOperations.<V, E>graphToSparseMatrix(graph, mWeightKey); for (int i = 0; i < matrix.rows(); i++) { for (int j = 0; j < matrix.columns(); j++) { writer.write(String.format("%4.2f ", matrix.getQuick(i, j))); } writer.write("\n"); } writer.close(); } catch (Exception e) { throw new RuntimeException("Error saving file: " + filename, e); } } }