Package edu.brown.graphs

Source Code of edu.brown.graphs.GraphUtil

package edu.brown.graphs;

import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.log4j.Logger;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONStringer;
import org.voltdb.catalog.Database;

import edu.brown.gui.common.GraphVisualizationPanel;
import edu.brown.logging.LoggerUtil;
import edu.brown.logging.LoggerUtil.LoggerBoolean;
import edu.brown.utils.ClassUtil;
import edu.brown.utils.CollectionUtil;
import edu.brown.utils.FileUtil;
import edu.brown.utils.JSONUtil;
import edu.brown.utils.StringUtil;
import edu.brown.utils.ThreadUtil;
import edu.uci.ics.jung.graph.util.Pair;

public abstract class GraphUtil {
    private static final Logger LOG = Logger.getLogger(GraphUtil.class);
    private static final LoggerBoolean debug = new LoggerBoolean();
    private static final LoggerBoolean trace = new LoggerBoolean();
    static {
        LoggerUtil.attachObserver(LOG, debug, trace);
    }

    public enum Members {
        ID,
        VERTEX_CLASS,
        VERTICES,
        EDGE_CLASS,
        EDGES,
    }

    /**
     * Remove all of the edges that are not incident to the given vertex
     * @param graph
     * @param v
     * @return Returns the set of edges that were removed
     */
    public static <V extends AbstractVertex, E extends AbstractEdge> Collection<E> removeEdgesWithoutVertex(IGraph<V, E> graph, V...vertices) {
        if (debug.val) LOG.debug("Removing edges that are not incident to " + Arrays.toString(vertices));
        Set<E> toRemove = new HashSet<E>();
        for (E e : graph.getEdges()) {
            boolean found = false;
            for (V v : vertices) {
                if (graph.isIncident(v, e)) {
                    found = true;
                    break;
                }
            } // FOR
            if (found == false) toRemove.add(e);
        } // FOR
        for (E e : toRemove) {
            graph.removeEdge(e);
        } // FOR
        return (toRemove);
    }
   
    /**
     * Remove any edges where the source and destination are the same vertex
     * @param graph
     * @return Returns the set of edges that were removed
     */
    public static <V extends AbstractVertex, E extends AbstractEdge> Collection<E> removeLoopEdges(IGraph<V, E> graph) {
        Set<E> toRemove = new HashSet<E>();
        for (E e : graph.getEdges()) {
            Collection<V> vertices = graph.getIncidentVertices(e);
            if (vertices == null) continue;
            if (vertices.size() == 1) {
                toRemove.add(e);
            }
            else if (CollectionUtil.first(vertices) == CollectionUtil.get(vertices, 1)) {
                toRemove.add(e);
            }
        } // FOR
        for (E e : toRemove) {
            graph.removeEdge(e);
        } // FOR
        return (toRemove);
    }
   
    /**
     *
     * @param graph
     * @return Returns the set of vertices that were removed
     */
    public static <V extends AbstractVertex, E extends AbstractEdge> Collection<V> removeDisconnectedVertices(IGraph<V, E> graph) {
        Set<V> toRemove = new HashSet<V>();
        for (V v : graph.getVertices()) {
            if (graph.getIncidentEdges(v).isEmpty()) {
                toRemove.add(v);
            }
        } // FOR
        for (V v : toRemove) {
            graph.removeVertex(v);
        }
        return (toRemove);
    }
   
    /**
     * Remove duplicate edges between every unique pair of vertices
     * @param graph
     */
    public static <V extends AbstractVertex, E extends AbstractEdge> void removeDuplicateEdges(IGraph<V, E> graph) {
        Set<E> toRemove = new HashSet<E>();
        for (V v0 : graph.getVertices()) {
            for (V v1 : graph.getVertices()) {
                Collection<E> edges = graph.findEdgeSet(v0, v1);
                if (edges == null || edges.size() <= 1) continue;
               
                toRemove.clear();
                boolean first = true;
                for (E e : edges) {
                    if (first) {
                        first = false;
                    } else {
                        toRemove.add(e);
                    }
                } // FOR
                for (E e : toRemove) {
                    graph.removeEdge(e);
                } // FOR
            } // FOR
        } // FOR
    }
   
    /**
     *
     * @param <V>
     * @param <E>
     * @param graph
     * @param path0
     * @param path1
     * @return
     */
    public static <V extends AbstractVertex, E extends AbstractEdge> String comparePathsDebug(IGraph<V, E> graph, List<V> path0, List<V> path1) {
        StringBuilder sb = new StringBuilder();

        final String match = "\u2713";
        final String conflict = "X";
       
        int ctr0 = 0;
        int cnt0 = path0.size();
       
        int ctr1 = 0;
        int cnt1 = path1.size();
       
        while (ctr0 < cnt0 || ctr1 < cnt1) {
            V v0 = null;
            if (ctr0 < cnt0) v0 = path0.get(ctr0++);
           
            V v1 = null;
            if (ctr1 < cnt1) v1 = path1.get(ctr1++);
           
            String status;
            if (v0 != null && v1 != null) {
                status = (v0.equals(v1) ? match : conflict);
            } else {
                status = conflict;
            }
            sb.append(String.format("| %s | %-50s | %-50s |\n", status, v0, v1));
            sb.append(StringUtil.repeat("-", 110)).append("\n");
        } // FOR
       
        return (sb.toString());
    }
   
   
    /**
     * For a given graph, write out a serialized form of it to the target output_path
     * @param <V>
     * @param <E>
     * @param graph
     * @param output_path
     * @throws Exception
     */
    public static <V extends AbstractVertex, E extends AbstractEdge> void save(IGraph<V, E> graph, File output_path) throws IOException {
        if (debug.val) LOG.debug("Writing out graph to '" + output_path + "'");
       
        JSONStringer stringer = new JSONStringer();
        try {
            stringer.object();
            GraphUtil.serialize(graph, stringer);
            stringer.endObject();
        } catch (Exception ex) {
            throw new IOException(ex);
        }
       
        String json = stringer.toString();
        try {
            FileUtil.writeStringToFile(output_path, JSONUtil.format(json));
        } catch (Exception ex) {
            throw new IOException(ex);
        }
        if (debug.val) LOG.debug("Graph was written out to '" + output_path + "'");
    }
   
    /**
     * For a given graph, write out its contents in serialized form into the provided Stringer
     * @param <V>
     * @param <E>
     * @param graph
     * @param stringer
     * @throws JSONException
     */
    public static <V extends AbstractVertex, E extends AbstractEdge> void serialize(IGraph<V, E> graph, JSONStringer stringer) throws JSONException {
        GraphUtil.serialize(graph, null, null, stringer);
    }
   
    /**
     * For a given graph, write out its contents in serialized form into the provided Stringer
     * Can provide sets of vertices or edges to not be serialized out
     * @param <V>
     * @param <E>
     * @param graph
     * @param ignore_v
     * @param ignore_e
     * @param stringer
     * @throws JSONException
     */
    @SuppressWarnings("unchecked")
    public static <V extends AbstractVertex, E extends AbstractEdge> void serialize(IGraph<V, E> graph, Collection<V> ignore_v, Collection<E> ignore_e, JSONStringer stringer) throws JSONException {
        int e_cnt = 0;
        int v_cnt = 0;
        int e_skipped = 0;
       
        // Graph ID
        stringer.key(Members.ID.name()).value(graph.getGraphId());
       
        // Vertices
        assert(graph.getVertexCount() > 0) : "Graph has no vertices";
        stringer.key(Members.VERTICES.name()).array();
        Class<V> v_class = null;
        Set<Long> all_vertices = new HashSet<Long>();
        for (V v : graph.getVertices()) {
            if (ignore_v != null && ignore_v.contains(v)) continue;
            if (v_class == null) {
                v_class = (Class<V>)v.getClass();
                if (debug.val) LOG.debug("Discovered vertex class: " + v_class.getName());
            }
            stringer.object();
            v.toJSON(stringer);
            stringer.endObject();
            all_vertices.add(v.getElementId());
            v_cnt++;
            if (trace.val) LOG.trace("V [" + v.getElementId() + "]");
        } // FOR
        stringer.endArray();
        stringer.key(Members.VERTEX_CLASS.name()).value(v_class.getName());
        if (debug.val) LOG.debug("# of Vertices: " + v_cnt);
       
        // Edges
        if (graph.getEdgeCount() > 0) {
            stringer.key(Members.EDGES.name()).array();
            Class<E> e_class = null;
            for (E e : graph.getEdges()) {
                if (ignore_e != null && ignore_e.contains(e)) continue;
                if (e_class == null) {
                    e_class = (Class<E>)e.getClass();
                    if (debug.val) LOG.debug("Discovered edge class: " + e_class.getName());
                }
                // Thread synchronization issue
                // This is an attempt to prevent us from writing out edges that have vertices
                // that were added in between the time that we originally wrote out the list of vertices
                V v0 = graph.getSource(e);
                V v1 = graph.getDest(e);
                if (v0 == null) {
                    Pair<V> pair = graph.getEndpoints(e);
                    v0 = pair.getFirst();
                    v1 = pair.getSecond();
                }
                assert(v0 != null) : e;
                assert(v1 != null) : e;
               
                if (ignore_v != null && (ignore_v.contains(v0) || ignore_v.contains(v1))) continue;
                if (all_vertices.contains(v0.getElementId()) && all_vertices.contains(v1.getElementId())) {
                    if (trace.val) LOG.trace(String.format("E [%d] %d => %d", e.getElementId(), v0.getElementId(), v1.getElementId()));
                    stringer.object();
                    e.toJSON(stringer);
                    stringer.endObject();
                    e_cnt++;
                } else {
                    e_skipped++;
                }
            } // FOR
            stringer.endArray();
            stringer.key(Members.EDGE_CLASS.name()).value(e_class.getName());
        }
        if (e_skipped > 0) LOG.warn(String.format("Skipped %d out of %d edges", e_skipped, graph.getEdgeCount()));
        if (debug.val) LOG.debug("# of Edges: " + e_cnt);
        return;
    }
   
    /**
     * Given a graph and a path to a serialized file, load in all of the vertices+edges into the graph
     * @param <V>
     * @param <E>
     * @param graph
     * @param catalog_db
     * @param path
     * @throws Exception
     */
    public static <V extends AbstractVertex, E extends AbstractEdge> void load(IGraph<V, E> graph, Database catalog_db, File path) throws IOException {
        if (debug.val) LOG.debug("Loading in serialized graph from '" + path + "'");
        String contents = FileUtil.readFile(path);
        if (contents.isEmpty()) {
            throw new IOException("The workload statistics file '" + path + "' is empty");
        }
        try {
            GraphUtil.deserialize(graph, catalog_db, new JSONObject(contents));
        } catch (Exception ex) {
            throw new IOException(ex);
        }
        if (debug.val) LOG.debug("Graph loading is complete");
        return;
    }
   
    /**
     * Deserialize the provided JSONObject into the Graph object
     * @param <V>
     * @param <E>
     * @param graph
     * @param catalog_db
     * @param jsonObject
     * @throws Exception
     */
    @SuppressWarnings("unchecked")
    public static <V extends AbstractVertex, E extends AbstractEdge> int deserialize(IGraph<V, E> graph, Database catalog_db, JSONObject jsonObject) throws JSONException {
        // Graph Id
        int id = jsonObject.getInt(Members.ID.name());
       
        // Vertices
        String v_className = jsonObject.getString(Members.VERTEX_CLASS.name());
       
        // 2011-07-13: Fix for MarkovVertex
        v_className = v_className.replace("markov.Vertex", "markov.MarkovVertex");
        Class<V> v_class = (Class<V>)ClassUtil.getClass(v_className);
        if (debug.val) LOG.debug("Vertex class is '" + v_class.getName() + "'");
       
        JSONArray jsonArray = jsonObject.getJSONArray(Members.VERTICES.name());
        for (int i = 0, cnt = jsonArray.length(); i < cnt; i++) {
            V vertex = null;
            try {
                vertex = v_class.newInstance();
            } catch (Exception ex) {
                LOG.fatal("Failed to create new instance of " + v_class.getName());
                throw new JSONException(ex);
            }
            JSONObject jsonVertex = jsonArray.getJSONObject(i);
            vertex.fromJSON(jsonVertex, catalog_db);
            graph.addVertex(vertex);
        } // FOR
       
        // Edges
        // If the EDGE_CLASS is missing, don't bother loading any edges
        if (jsonObject.has(Members.EDGE_CLASS.name())) {
            String e_className = jsonObject.getString(Members.EDGE_CLASS.name());
           
            // 2011-07-13: Fix for MarkovVertex
            e_className = e_className.replace("markov.Edge", "markov.MarkovEdge");
            Class<E> e_class = (Class<E>)ClassUtil.getClass(e_className);
            if (debug.val) LOG.debug("Edge class is '" + v_class.getName() + "'");
           
            jsonArray = jsonObject.getJSONArray(Members.EDGES.name());
            for (int i = 0, cnt = jsonArray.length(); i < cnt; i++) {
                E edge = ClassUtil.newInstance(e_class, new Object[] { graph }, new Class<?>[]{ IGraph.class });
                JSONObject jsonEdge = jsonArray.getJSONObject(i);
                edge.fromJSON(jsonEdge, catalog_db);
            } // FOR
        }
       
        return (id);
    }
   
    /**
     *
     * @param <V>
     * @param <E>
     * @param graph
     */
    @SuppressWarnings("unchecked")
    public static <V extends AbstractVertex, E extends AbstractEdge> void visualizeGraph(IGraph<V, E> graph) {
        GraphVisualizationPanel.createFrame(graph).setVisible(true);
        ThreadUtil.sleep(10000);
    }
   
}
TOP

Related Classes of edu.brown.graphs.GraphUtil

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.