edu.uci.ics.jung.io.BipartiteGraphReader.java Source code

Java tutorial

Introduction

Here is the source code for edu.uci.ics.jung.io.BipartiteGraphReader.java

Source

/*
 * Created on Apr 13, 2004
 *
 * Copyright (c) 2004, 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.
 */
package edu.uci.ics.jung.io;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;

import org.apache.commons.collections.Predicate;

import edu.uci.ics.jung.graph.Edge;
import edu.uci.ics.jung.graph.Graph;
import edu.uci.ics.jung.graph.KPartiteGraph;
import edu.uci.ics.jung.graph.Vertex;
import edu.uci.ics.jung.graph.decorators.EdgeWeightLabeller;
import edu.uci.ics.jung.graph.decorators.StringLabeller;
import edu.uci.ics.jung.graph.decorators.StringLabeller.UniqueLabelException;
import edu.uci.ics.jung.graph.impl.DirectedSparseEdge;
import edu.uci.ics.jung.graph.impl.KPartiteSparseGraph;
import edu.uci.ics.jung.graph.impl.UndirectedSparseEdge;
import edu.uci.ics.jung.graph.predicates.UserDatumVertexPredicate;
import edu.uci.ics.jung.utils.TypedVertexGenerator;
import edu.uci.ics.jung.utils.UserData;
import edu.uci.ics.jung.utils.VertexGenerator;

/**
 * 
 * @author Joshua O'Madadhain
 */
public class BipartiteGraphReader {
    /**
     * The user data key for the vertices' partitions.
     */
    public final static String PARTITION = "edu.uci.ics.jung.io:Partition";

    /**
     * The predicate for the vertices in partitions A and B.
     */
    public final static UserDatumVertexPredicate PART_A = new UserDatumVertexPredicate(PARTITION, "vertex_ID_A");
    public final static UserDatumVertexPredicate PART_B = new UserDatumVertexPredicate(PARTITION, "vertex_ID_B");

    /**
     * <p>If <code>true</code>, specifies that each line of input implicitly 
     * represents a list of edges, where the first token specifies one endpoint,
     * and the subsequent tokens specify a sequence of opposite endpoints.
     * Otherwise, each line of input represents a single edge.</p>
     */
    protected boolean asList;

    /**
     * <p>If <code>true</code>, the edges created
     * will be directed; otherwise, they will be undirected.
     * In either case, the graph is constrained to accept only the 
     * specified edge type.</p>
     * 
     * <p>NOTE: Currently, the data format specified only permits 
     * directed edges whose source is in partition A and whose
     * destination is in partition B.</p>
     */
    protected boolean directed;

    /**
     * <p>
     * If <code>true</code>, parallel edges may
     * be created if the edge is found more than once in the input file.
     * Otherwise, each edge is labelled with a weight by an 
     * <code>EdgeWeightLabeller</code>, and the graph is created with the
     * "no parallel edges" constraint.
     * The weight of each edge in the non-parallel case is the number of times 
     * that the edge is represented in the input file (that is, the edge's multiplicity).
     * </p>
     */
    protected boolean parallel;

    public BipartiteGraphReader(boolean asList, boolean directed, boolean parallel) {
        this.asList = asList;
        this.directed = directed;
        this.parallel = parallel;
    }

    /**
     * Creates a BipartiteGraphReader with default behavior (one edge per line, 
     * undirected, no parallel edges created).
     */
    public BipartiteGraphReader() {
        this(false, false, false);
    }

    /**
     * <p>Creates a <code>KPartiteGraph</code> (where k = 2) based on connection
     * data gathered from a Reader.  
     * The data must be in one of the two following formats:</p>
     * 
     * <pre>
     * a_1 b_1 
     * a_2 b_1 
     * a_2 b_2 
     * a_3 b_3 ...
     * </pre>
     * 
     * <p>or</p>
     * 
     * <pre>
     *  a_1 b_1 b_2 b_3 
     *  a_2 b_2 b_3 
     *  a_3 b_3 ...
     * </pre>
     * 
     * <p>
     * where <code>x_i</code> is a unique label (ID) for vertex <code>i</code>
     * in partition <code>x</code>. Each line in the file defines an edge
     * between the specified vertices. The vertices themselves are defined
     * implicitly: if a label is read from the file for which no vertex yet
     * exists, a new vertex is created and that label is attached to it.
     * </p>
     * 
     * <p>The first format is the default; the second is assumed if the 
     * <code>asList</code> flag is set to <code>true</code>.  In
     * the default format, everything after the first whitespace is 
     * interpreted as part of the label for the second vertex.</p>
     * 
     * <p>
     * Vertex labels are only required to be unique within their
     * partitions. Each partition has its own <code>StringLabeller</code>,
     * which is accessed via the key <code>VID_A</code> or <code>VID_B</code>,
     * as appropriate.
     * </p>
     * 
     * <p>
     * The end of the file may be artificially set by putting the string <code>end_of_file</code>
     * on a line by itself.
     * </p>
     * 
     *  
     * 
     * @return the 2-partite graph loaded with these vertices, and labelled with two StringLabellers
     * @throws
     *         IOException  May occur in the course of reading from a stream.
     */
    public KPartiteGraph load(Reader reader) throws IOException {
        List predicates = new LinkedList();
        predicates.add(PART_A);
        predicates.add(PART_B);

        KPartiteGraph bg = new KPartiteSparseGraph(predicates, true);

        Collection edge_constraints = bg.getEdgeConstraints();
        if (directed)
            edge_constraints.add(Graph.DIRECTED_EDGE);
        else
            edge_constraints.add(Graph.UNDIRECTED_EDGE);
        if (!parallel)
            edge_constraints.add(Graph.NOT_PARALLEL_EDGE);

        VertexGenerator vg = new TypedVertexGenerator(edge_constraints);

        EdgeWeightLabeller ewl = EdgeWeightLabeller.getLabeller(bg);

        BufferedReader br = new BufferedReader(reader);

        while (br.ready()) {
            // read the line in, break it into 2 parts (one for each
            // vertex)
            String curLine = br.readLine();
            if (curLine == null || curLine.equals("end_of_file"))
                break;
            if (curLine.trim().length() == 0)
                continue;
            String[] parts;
            if (asList)
                parts = curLine.trim().split("\\s+");
            else
                parts = curLine.trim().split("\\s+", 2);

            // fetch/create vertices for each part of the string
            Vertex v_a = getOrCreateVertexByName(bg, vg, parts[0], PART_A);

            int i = 1;
            while (i < parts.length) {
                Vertex v_b = getOrCreateVertexByName(bg, vg, parts[i++], PART_B);

                Edge e = v_a.findEdge(v_b);
                boolean absent = (e == null);
                if (absent || parallel) {
                    if (directed)
                        e = bg.addEdge(new DirectedSparseEdge(v_a, v_b));
                    else
                        e = bg.addEdge(new UndirectedSparseEdge(v_a, v_b));
                }
                if (!parallel) // weight represents multiplicity of edge
                {
                    if (absent)
                        ewl.setWeight(e, 1);
                    else
                        ewl.setWeight(e, ewl.getWeight(e) + 1);
                }
            }
        }
        br.close();
        reader.close();
        return bg;
    }

    private static Vertex getOrCreateVertexByName(Graph bg, VertexGenerator vg, String label,
            UserDatumVertexPredicate partition) {
        StringLabeller vID_label = StringLabeller.getLabeller(bg, partition);
        Vertex v = (Vertex) vID_label.getVertex(label);
        if (v == null) {
            v = (Vertex) vg.create();
            v.addUserDatum(partition.getKey(), partition.getDatum(), UserData.SHARED);
            bg.addVertex(v);
            try {
                vID_label.setLabel(v, label);
            } catch (UniqueLabelException e1) {
            }
        }
        return v;
    }

    public static Predicate getPartition(Vertex v) {
        if (PART_A.evaluate(v))
            return PART_A;
        else if (PART_B.evaluate(v))
            return PART_B;
        else
            throw new IllegalArgumentException("Specified vertex " + v + "is not in any registered partition");
    }

    public void setAsList(boolean asList) {
        this.asList = asList;
    }

    public void setDirected(boolean directed) {
        this.directed = directed;
    }

    public void setParallel(boolean parallel) {
        this.parallel = parallel;
    }

    public boolean isAsList() {
        return asList;
    }

    public boolean isDirected() {
        return directed;
    }

    public boolean isParallel() {
        return parallel;
    }
}