Skip to content

Class Graph

Ori Roth edited this page Apr 2, 2017 · 3 revisions

Synopsis of Class Graph

public class Graph<Data> implements Checkable { 
    /*
     * Type (4)
     */
        final Vertex<Data>[] vertices; 
        final Edge<Data>[] edges; 
        void invariant(); 
        void reset(); 
    /*
     * Nested types (3)
     */
        static class Edge<Data> implements Checkable, Comparable<Edge<Data>> { ... } 
        static class Vertex<Data> implements Comparable<Vertex<Data>> { ... } 
        static class Builder<Data> { ... } 
} 

Output types*: Comparable<Data>, Edge<Data>, Vertex<Data>.

Synopsis of Class Graph.Edge

public static class Graph.Edge<Data> implements Checkable, Comparable<Edge<Data>> { 
    /*
     * Type (4)
     */
        final Vertex<Data> from; 
        final Vertex<Data> to; 
        void invariant(); 
        int compareTo(Edge<Data> o); 
} 

Input types: Comparable<Data>.

Output types: Comparable<Data>, Vertex<Data>.

Synopsis of Class Graph.Vertex

public static class Graph.Vertex<Data> implements Comparable<Vertex<Data>> { 
    /*
     * Type (9)
     */
        final Vertex<Data>[] to; 
        final Vertex<Data>[] from; 
        final Data data; 
        final int i; 
        void reset(); 
        void visit(); 
        boolean isVisited(); 
        String toString(); 
        final int compareTo(Vertex<Data> o); 
}

*Input types: Comparable<Data>.

Output types: Comparable<Data>.

Synopsis of Class Graph.Builder

public static class Graph.Builder<Data> { 
    /*
     * Forge (1)
     */
        Builder(); 
    /*
     * Type (3)
     */
        void newEdge(Data from, Data to); 
        void newVertex(Data d); 
        Graph<Data> build(); 
} 

Input types: Comparable<Data>.

Output types: Comparable<Data>, Graph<Data>.

Synopsis of Class Graph.Builder.Pair

private static class Graph.Builder.Pair<Data> { 
    /*
     * Forge (1)
     */
        Pair(Data first, Data second); 
    /*
     * Type (2)
     */
        int hashCode(); 
        boolean equals(Object o); 
} 

Code

// SSDLPedia
package il.ac.technion.cs.cs236700.graph;

import static il.ac.technion.cs.ssdl.utils.DBC.*;
import il.ac.technion.cs.ssdl.stereotypes.Classical;
import il.ac.technion.cs.ssdl.stereotypes.Immutable;
import il.ac.technion.cs.ssdl.stereotypes.Instantiable;
import il.ac.technion.cs.ssdl.utils.All;
import il.ac.technion.cs.ssdl.utils.DBC.Checkable;

import java.util.*;

/**
 * Class Graph: a class representing an immutable directed graph with
 * arbitrary data contained in its nodes. The design supports graph visitation,
 * with a facility to mark (and unmark) vertices as visited.
 * 
 * <Data> Kind of elements stored in each of the graph vertices. This
 *            data type must implement correctly both #equals(Object)
 *            and Comparable#compareTo(Object).
 * Author: Yossi Gil 
 * See:  20/06/2007
 */
@Instantiable @Immutable @Classical public class Graph<Data extends Comparable<Data>> implements Checkable {
    /**
     * An immutable array of all vertices of this graph
     */
    public final Vertex<Data>[] vertices;
    /**
     * An immutable array of all edges of this graph
     */
    public final Edge<Data>[] edges;
    
    public void invariant() {
        nonnull(vertices);
        nonnull(edges);
        sure(All.notNull(vertices));
        sure(All.notNull(edges));
        for (final Vertex<Data> v : vertices) {
            nonnull(v);
            sure(vertices[v.i] == v);
            for (final Vertex<Data> u : v.from) {
                nonnull(u);
                sure(Arrays.binarySearch(vertices, u) >= 0);
                sure(Arrays.binarySearch(u.to, v) >= 0);
            }
            for (final Vertex<Data> u : v.to) {
                nonnull(u);
                sure(Arrays.binarySearch(vertices, u) >= 0);
                sure(Arrays.binarySearch(u.from, v) >= 0);
            }
        }
        for (final Edge<Data> e : edges) {
            nonnull(e);
            nonnull(e.from);
            nonnull(e.to);
            sure(Arrays.binarySearch(vertices, e.from) >= 0);
            sure(Arrays.binarySearch(vertices, e.to) >= 0);
        }
    }
    
    /**
     * Mark all vertices of this graph unvisited
     */
    public void reset() {
        for (final Vertex<Data> v : vertices)
            v.reset();
    }
    
    private Graph(final Vertex<Data>[] vertices, final Edge<Data>[] edges) {
        nonnull(vertices);
        nonnull(edges);
        require(All.notNull(vertices));
        require(All.notNull(edges));
        this.vertices = vertices;
        this.edges = edges;
    }
    
    protected Graph(final Graph<Data> other) {
        this(other.vertices, other.edges);
    }
    
    /**
     * Class Graph.Edge: Represents an edge in a Graph.
     * 
     * <Data> the type of information stored in a graph node
     * Author: Yossi Gil 
 * See:  28/06/2007
     */
    public static class Edge<Data extends Comparable<Data>> implements Checkable, Comparable<Edge<Data>> {
        /**
         * where this edge starts
         */
        public final Vertex<Data> from;
        /**
         * where this edge ends
         */
        public final Vertex<Data> to;
        
        public void invariant() {
            nonnull(from);
            nonnull(to);
        }
        
        private Edge(final Vertex<Data> from, final Vertex<Data> to) {
            this.from = from;
            this.to = to;
        }
        
        public int compareTo(final Edge<Data> o) {
            final int $ = from.compareTo(o.from);
            return $ != 0 ? $ : to.compareTo(o.to);
        }
    }
    
    /**
     * Class Graph.Vertex: an immutable class representing a vertex in a
     * Graph
     * 
     * <Data> the type of information stored in each vertex.
     * Author: Yossi Gil 
 * See:  28/06/2007
     */
    public static class Vertex<Data extends Comparable<Data>> implements Comparable<Vertex<Data>> {
        /**
         * Vertices to which there is an edge from this vertex.
         */
        public final Vertex<Data> to[];
        /**
         * Vertices from which there is an edge leading to this vertex.
         */
        public final Vertex<Data> from[];
        /**
         * The data stored in this node.
         */
        public final Data data;
        /**
         * The ordinal number of this node in its containing graph.
         */
        public final int i;
        /**
         * Was this node visited?
         */
        private boolean visited;
        
        private Vertex(final Vertex<Data>[] from, final Vertex<Data>[] to, final Data attributes, final int i) {
            this.from = from;
            this.to = to;
            this.data = attributes;
            this.i = i;
        }
        
        /**
         * Reset this vertex. That is, the visited flag is set to
         * false.
         */
        public void reset() {
            visited = false;
        }
        
        /**
         * Marks this instance as visited. That is, the visited flag becomes
         * true.
         */
        public void visit() {
            visited = true;
        }
        
        /**
         * check the visitation status.
         * 
         * Return: true if this vertex was visited.
         */
        public boolean isVisited() {
            return visited;
        }
        
        /**
         * Returns toString() of the attributes and the number of
         * incoming and outgoing arcs.
         */
        @Override public String toString() {
            String $ = data == null ? super.toString() : data.toString();
            $ += " [" + from.length + " in, ";
            $ += to.length + " out]";
            return $;
        }
        
        public final int compareTo(final Vertex<Data> o) {
            nonnull(data);
            nonnull(o);
            nonnull(o.data);
            return data.compareTo(o.data);
        }
    }
    
    /**
     * Class Graph.Builder: A class to create a Graph from a
     * bunch of associations. The associations are added incrementally, with
     * function {@link #newEdge(Comparable, Comparable)} called for each
     * association, then function #build() is invoked to actually create
     * the graph. Vertices are created implicitly, i.e., the graph has only
     * vertices which participated in an association.
     * 
     * Author: Yossi Gil 
 * See:  20/06/2007
     * <Data> Kind of information stored in graph vertices
     */
    public static class Builder<Data extends Comparable<Data>> {
        private final HashSet<Pair<Data>> edges = new HashSet<Pair<Data>>();
        
        /**
         * Record an association between two data elements- later to be shown as
         * a graph edge.
         * 
         * from association starts here
         * to association ends here
         */
        public void newEdge(final Data from, final Data to) {
            nonnull(from);
            nonnull(to);
            newVertex(from);
            newVertex(to);
            edges.add(new Pair<Data>(from, to));
        }
        
        public void newVertex(final Data d) {
            nonnull(d);
            vertices.put(d, emptyPair());
        }
        
        private final TreeMap<Data, Pair<HashSet<Data>>> vertices = new TreeMap<Data, Pair<HashSet<Data>>>();
        
        /**
         * The actual function to create the graph, defined by all associations
         * recorded so far.
         * 
         * Return: th Graph objects odefined by the associations.
         */
        @SuppressWarnings("synthetic-access")//
        public Graph<Data> build() {
            // Phase I: Determine vertex set, and record mappings.
            for (final Pair<Data> edge : edges) {
                final Data from = edge.first;
                final Data to = edge.second;
                vertices.get(from).second.add(to);
                vertices.get(to).first.add(from);
            }
            // Phase II: create vertex array.
            final Graph.Vertex<Data>[] vs = newVertexArray(vertices.size());
            {
                int i = 0;
                for (final Data d : vertices.keySet()) {
                    final Graph.Vertex<Data>[] from = newVertexArray(vertices.get(d).first.size());
                    final Graph.Vertex<Data>[] to = newVertexArray(vertices.get(d).second.size());
                    vs[i] = new Graph.Vertex<Data>(from, to, d, i);
                    record(d, vs[i]);
                    i++;
                }
            }
            // Phase III: fill vertex array.
            for (final Data d : vertices.keySet()) {
                final Graph.Vertex<Data> v = find(d);
                fill(v.from, vertices.get(d).first);
                fill(v.to, vertices.get(d).second);
            }
            // Phase IV: create and fill edges array
            final Graph.Edge<Data>[] es = newEdgeArray(edges.size());
            {
                int i = 0;
                for (final Pair<Data> p : edges)
                    es[i++] = new Graph.Edge<Data>(find(p.first), find(p.second));
            }
            Arrays.sort(es);
            ensure(es.length == edges.size());
            return new Graph<Data>(vs, es);
        }
        
        private void fill(final Graph.Vertex<Data> a[], final Collection<Data> ds) {
            require(a.length == ds.size());
            int i = 0;
            for (final Data d : ds)
                a[i++] = find(d);
            Arrays.sort(a);
        }
        
        @SuppressWarnings("unchecked")//
        private Graph.Vertex<Data>[] newVertexArray(final int n) {
            return new Graph.Vertex[n];
        }
        
        @SuppressWarnings("unchecked")//
        private Graph.Edge<Data>[] newEdgeArray(final int n) {
            return new Graph.Edge[n];
        }
        
        private Pair<HashSet<Data>> emptyPair() {
            return new Pair<HashSet<Data>>(emptySet(), emptySet());
        }
        
        private HashSet<Data> emptySet() {
            return new HashSet<Data>();
        }
        
        private final HashMap<Data, Graph.Vertex<Data>> data2vertex = new HashMap<Data, Graph.Vertex<Data>>();
        
        private void record(final Data d, final Graph.Vertex<Data> v) {
            data2vertex.put(d, v);
        }
        
        private Graph.Vertex<Data> find(final Data d) {
            return data2vertex.get(d);
        }
        
        private static class Pair<Data> {
            Data first;
            Data second;
            
            public Pair(final Data first, final Data second) {
                nonnull(first);
                nonnull(second);
                this.first = first;
                this.second = second;
            }
            
            @Override public int hashCode() {
                return first.hashCode() >>> 1 ^ second.hashCode();
            }
            
            @Override public boolean equals(final Object o) {
                nonnull(o);
                require(o instanceof Pair);
                nonnull(first);
                nonnull(second);
                @SuppressWarnings("unchecked") final Pair<Data> other = (Pair<Data>) o;
                nonnull(other.first);
                nonnull(other.second);
                return first.equals(other.first) && second.equals(other.second);
            }
        }
    }
}

Metrics

Metric Value Acronym Explanation
LOC 343 Lines Of Code Total number of lines in the code
SCC 118 SemiColons Count Total number of semicolon tokens found in the code.
NOT 1764 Number Of Tokens Comments, whitespace and text which cannot be made into a token not included.
VCC 7417 Visible Characters Count The total number of non-white (i.e., not space, tab, newline, carriage return, form feed) characters.
CCC 5085 Code Characters Count Total number of non-white characters in tokens. White space characters in string and character literals are not counted.
UIC 87 Unique Identifiers Count The number of different identifiers found in the code
WHC 7 Weighted Horizontal Complexity A heuritistic on horizontal complexity

Statistics

Statitic Value
Average token length 2.9
Tokens/line 5.1
Visible characters/line 22
Code characters/line 15
Semicolons/tokens 6%
Comment text percentage 31%

Tokens by kind

Token Kind Occurrences
KEYWORD 195
OPERATOR 187
LITERAL 18
ID 633
PUNCTUATION 731
COMMENT 28
OTHER 682
Clone this wiki locally