coq.DebugUnivInconst.java Source code

Java tutorial

Introduction

Here is the source code for coq.DebugUnivInconst.java

Source

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package coq;

import edu.uci.ics.jung.algorithms.filters.VertexPredicateFilter;
import edu.uci.ics.jung.algorithms.layout.FRLayout;
import edu.uci.ics.jung.algorithms.shortestpath.BFSDistanceLabeler;
import edu.uci.ics.jung.graph.DirectedSparseMultigraph;
import edu.uci.ics.jung.graph.Graph;
import edu.uci.ics.jung.graph.SparseMultigraph;
import edu.uci.ics.jung.graph.util.EdgeType;
import edu.uci.ics.jung.visualization.VisualizationViewer;
import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse;
import edu.uci.ics.jung.visualization.control.ModalGraphMouse;
import edu.uci.ics.jung.visualization.decorators.ToStringLabeller;
import edu.uci.ics.jung.visualization.renderers.Renderer;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Paint;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.swing.JFrame;
import org.apache.commons.collections15.Predicate;
import org.apache.commons.collections15.Transformer;
import org.jgrapht.alg.StrongConnectivityInspector;
import org.jgrapht.graph.DefaultEdge;
import org.jgrapht.graph.SimpleDirectedGraph;

/**
 *
 * @author Abhishek
 */
public class DebugUnivInconst {
    JFrame topUnivs = null;

    /**
     * 
     * @param constraints : the string containing the output of "Print Universes."
     * @return a list of constraint objects
     */
    static ArrayList<Constraint> parseConstraints(String constraints) {
        String[] lines = constraints.split("\n");
        String curLHS = "";
        ArrayList<Constraint> ret = new ArrayList<Constraint>();
        for (String line : lines) {
            if (line.trim().isEmpty())
                continue;

            Constraint constr = new Constraint(line);

            if (constr.lhs.isEmpty())
                constr.lhs = curLHS;
            else
                curLHS = constr.lhs;

            ret.add(constr);
        }
        return ret;
    }

    void showTopUnivs(String constraints) {
        ArrayList<Constraint> cts = parseConstraints(constraints);
        DirectedSparseMultigraph<String, String> g = new DirectedSparseMultigraph<String, String>();
        for (int i = 0; i < cts.size(); i++) {
            Constraint constr = cts.get(i);
            if (constr.involvesTop())
                constr.addToGraph(g, i + 1);
        }

        showGraph(makeEqualitiesUndirected(g), true, "Univ. levels in Top module", new HashSet<String>());

    }

    static class EdgeColor implements Transformer<String, Paint> {

        @Override
        public Paint transform(String edgeLabel) {
            if (edgeLabel.startsWith("s")) // <=
                return Color.RED;
            else if (edgeLabel.startsWith("n")) // <
                return Color.GREEN;
            else
                return Color.BLUE; // =
        }
    }

    static class FilterNodesOut implements Predicate<String> {
        Set<String> filterOut;

        public FilterNodesOut(Set<String> filterOut) {
            this.filterOut = filterOut;
        }

        @Override
        public boolean evaluate(String t) {
            return !(filterOut.contains(t));
        }
    }

    static class FilterKeepNodes implements Predicate<String> {
        Set<String> keepNodes;

        public FilterKeepNodes(Set<String> keepNodes) {
            this.keepNodes = keepNodes;
        }

        @Override
        public boolean evaluate(String t) {
            return (keepNodes.contains(t));
        }
    }

    static class FilterLeavesOut implements Predicate<String> {
        Graph<String, Object> graph;

        public FilterLeavesOut(Graph graph) {
            this.graph = graph;
        }

        @Override
        public boolean evaluate(String t) {
            return (graph.getNeighborCount(t) > 1);
            // if a variable(vertex) has only 1 constraint, it can be trivially solved
        }
    }

    static class VertexColor implements Transformer<String, Paint> {
        HashSet<String> highlightNodes;

        public VertexColor(HashSet<String> highlightNodes) {
            this.highlightNodes = highlightNodes;
        }

        @Override
        public Paint transform(String node) {

            if (highlightNodes.contains(node))
                return Color.CYAN;
            else
                return Color.GREEN;
        }

    }

    void showGraph(Graph g, boolean newWindow, String title, HashSet<String> highlightNodes) {
        FRLayout<String, String> layout = new FRLayout<String, String>(g);
        System.err.println("----- " + title + "------");
        System.out.println("#edges: " + g.getEdgeCount());
        System.out.println("#nodes: " + g.getVertexCount());
        System.err.println("-----------------------");
        int numV = g.getVertexCount();
        layout.setSize(new Dimension(Math.max(600, numV), Math.max(600, numV)));
        VisualizationViewer<String, String> vv = new VisualizationViewer<String, String>(layout);
        DefaultModalGraphMouse gm = new DefaultModalGraphMouse();
        gm.setMode(ModalGraphMouse.Mode.PICKING);
        vv.setGraphMouse(gm);
        vv.getRenderContext().setVertexDrawPaintTransformer(new VertexColor(highlightNodes));
        vv.getRenderContext().setVertexFillPaintTransformer(new VertexColor(highlightNodes));
        vv.getRenderContext().setArrowDrawPaintTransformer(new EdgeColor());
        vv.getRenderContext().setArrowFillPaintTransformer(new EdgeColor());
        vv.getRenderContext().setEdgeDrawPaintTransformer(new EdgeColor());
        vv.getRenderContext().setVertexLabelTransformer(new ToStringLabeller<String>());
        vv.getRenderer().getVertexLabelRenderer().setPosition(Renderer.VertexLabel.Position.CNTR);

        JFrame jd;
        if (newWindow || topUnivs == null) {
            jd = new JFrame();
            jd.setTitle(title);
            jd.setSize(new Dimension(1000, 800));
            // jd.pack();
        } else {
            jd = topUnivs;
        }

        if (topUnivs == null && !newWindow)
            topUnivs = jd;

        jd.getContentPane().removeAll();
        jd.getContentPane().add(vv);
        jd.setVisible(true);

    }

    static class Constraint {
        public String lhs, rhs, edgetype;

        public static String LESS_THAN = "s";

        public Constraint(String lhs, String rhs, String line) {
            this.lhs = lhs;
            this.rhs = rhs;
            if (line.contains("<="))
                edgetype = "n";
            else if (line.contains("<"))
                edgetype = LESS_THAN;
            else
                edgetype = "e";
        }

        boolean involvesTop() {
            return lhs.startsWith("Top.") || rhs.startsWith("Top.");
        }

        public Constraint(String line) {
            String frags[] = line.split("[<=]");
            if (frags.length == 3) {
                edgetype = "n"; // not strict inequality (<=)
                lhs = frags[0].trim();
                assert (frags[1].isEmpty());
                rhs = frags[2].trim();
            } else {
                assert (frags.length == 2);

                lhs = frags[0].trim();
                rhs = frags[1].trim();
                if (line.contains("<"))
                    edgetype = LESS_THAN; // strict inequality (<)
                else {
                    assert (line.contains("="));
                    edgetype = "e"; // equality (=)
                }
            }
        }

        public void addHelpfulNames(HashMap<String, String> help) {
            if (help == null || help.isEmpty())
                return;

            if (help.containsKey(lhs))
                lhs = help.get(lhs);

            if (help.containsKey(rhs))
                rhs = help.get(rhs);

        }

        public void addToGraph(Graph<String, String> g, int i) {
            String edgelabel = edgetype + i;
            assert (!lhs.isEmpty());
            assert (!rhs.isEmpty());
            g.addVertex(lhs);
            g.addVertex(rhs);
            //EdgeType edt=EdgeType.DIRECTED;

            //if(edgetype.equals("e"))
            //edt=EdgeType.UNDIRECTED;
            boolean bl = g.addEdge(edgelabel, rhs, lhs, EdgeType.DIRECTED);
            assert (bl);// arrow can be read as <,i.e for a<b, arrow is at a.                

        }

        boolean isStrict() {
            return edgetype.equals(LESS_THAN);
        }

        static ArrayList<Constraint> keepStrictEdges(ArrayList<Constraint> constraints) {
            ArrayList<Constraint> ret = new ArrayList<Constraint>();
            for (Constraint constr : constraints) {
                if (constr.isStrict())
                    ret.add(constr);
            }

            return ret;
        }
    }

    Set<String> getVerticesToDiscard(Graph<String, String> g, String lhs, String rhs) {
        // wrong because equalities need to be bidirectional
        BFSDistanceLabeler<String, String> bfs = new BFSDistanceLabeler<String, String>();
        HashSet<String> roots = new HashSet<String>(2);
        roots.add(lhs);
        roots.add(rhs);
        bfs.labelDistances(g, roots);
        return bfs.getUnvisitedVertices();
    }

    /**
     * 
     * @param s1
     * @param s2
     * @return 
     */
    static boolean nonDisjoint(HashSet<String> highlight, Set<String> scc) {
        if (highlight.isEmpty())
            return true;

        HashSet<String> highCopy = new HashSet<String>(highlight);
        highCopy.retainAll(scc);
        return (highCopy.size() > 0);
    }

    static ArrayList<Set<String>> keepBadSCCs(List<Set<String>> sccs, ArrayList<Constraint> strictConstraints,
            HashSet<String> highlight) {
        ArrayList<Set<String>> ret = new ArrayList<Set<String>>();
        for (Set<String> scc : sccs)
            if (containsAStrictInequality(scc, strictConstraints) && nonDisjoint(highlight, scc))
                ret.add(scc);

        return ret;
    }

    static boolean containsAStrictInequality(Set<String> scc, ArrayList<Constraint> strictConstraints) {
        for (Constraint constr : strictConstraints)
            if (scc.contains(constr.lhs) && scc.contains(constr.rhs))
                return true;

        return false;
    }

    ArrayList<Set<String>> getVerticesToKeepJgraph(DirectedSparseMultigraph<String, String> g,
            HashSet<String> highlightHodes, ArrayList<Constraint> strictConstraints) {
        SimpleDirectedGraph<String, String> jg = new SimpleDirectedGraph(DefaultEdge.class);
        Collection<String> edges = g.getEdges();
        for (String ed : edges) {
            String srcv = g.getSource(ed);
            String destv = g.getDest(ed);
            jg.addVertex(srcv);
            jg.addVertex(destv);
            jg.addEdge(srcv, destv, ed);
            if (ed.startsWith("e"))
                jg.addEdge(destv, srcv, ed);
        }

        StrongConnectivityInspector<String, String> insp = new StrongConnectivityInspector(jg);
        List<Set<String>> stronglyConnectedSets = insp.stronglyConnectedSets();
        //dbugcontents=dbugcontents+"\n\n\n found #SCCs"+stronglyConnectedSets+"\n\n";

        ArrayList<Set<String>> badSCCs = keepBadSCCs(stronglyConnectedSets, strictConstraints, highlightHodes);
        return badSCCs;
    }

    SparseMultigraph<String, String> makeEqualitiesUndirected(DirectedSparseMultigraph<String, String> g) {
        SparseMultigraph<String, String> ret = new SparseMultigraph<String, String>();
        Collection<String> edges = g.getEdges();
        for (String ed : edges) {
            String srcv = g.getSource(ed);
            String destv = g.getDest(ed);
            ret.addVertex(srcv);
            ret.addVertex(destv);
            EdgeType et = EdgeType.DIRECTED;
            if (ed.startsWith("e"))
                et = EdgeType.UNDIRECTED;
            ret.addEdge(ed, srcv, destv, et);
        }

        return ret;
    }

    DirectedSparseMultigraph<String, String> filterKeepAndVisualize(DirectedSparseMultigraph<String, String> g,
            Set<String> keepV, HashSet<String> highlightNodes, String windowTitle) {
        //dbugcontents=dbugcontents+"\n init # nodes:"+g.getVertexCount()+" # edges:"+ g.getEdgeCount();
        //dbugcontents=dbugcontents+"nodes left in SCC(#nodes):"+keepV.size();
        //init # nodes:1060 # edges:2911filtering removed(#nodes):943
        VertexPredicateFilter<String, String> vf =
                //new VertexPredicateFilter<String, String>(new FilterNodesOut(discardv));
                new VertexPredicateFilter<String, String>(new FilterKeepNodes(keepV));
        DirectedSparseMultigraph<String, String> filtered = (DirectedSparseMultigraph<String, String>) vf
                .transform(g);
        //uiWindow.enableCompileButtonsAndShowDbug();
        Collection<String> edges = filtered.getEdges();
        int count = 0;
        for (String s : edges) {
            count = count + 1;
            //dbugcontents=dbugcontents+s+"\n";
        }
        //dbugcontents=dbugcontents+"\n\n"+count+" both edges: \n\n";

        count = 0;
        edges = g.getEdges();
        for (String s : edges) {
            count = count + 1;
            if (s.startsWith("s") && (keepV.contains(g.getSource(s)) || keepV.contains(g.getDest(s)))) {
                //dbugcontents=dbugcontents+s+"\n";
                filtered.addEdge(s, g.getSource(s), g.getDest(s));
            }
        }
        //dbugcontents=dbugcontents+"\n\n"+count+" finish s edges: \n\n";

        //uiWindow.enableCompileButtonsAndShowDbug();

        showGraph(makeEqualitiesUndirected(filtered), true, windowTitle, highlightNodes);
        return filtered;
    }

    HashMap<String, String> helpfulConstrNames = null;

    void parseNames(String input) {
        if (helpfulConstrNames == null)
            helpfulConstrNames = new HashMap<String, String>();
        helpfulConstrNames.clear();

        String[] lines = input.split("\n");
        for (String line : lines) {
            String[] frags = line.split(":");
            helpfulConstrNames.put(frags[0], frags[1]);
            System.out.println("mapping " + frags[0] + " to " + frags[1]);
        }
    }

    int debugUnivInconsistency(ArrayList<Constraint> cts, HashSet<String> highlightNodes) {
        System.out.println("#constraints:" + cts.size());

        DirectedSparseMultigraph<String, String> g = new DirectedSparseMultigraph<String, String>();
        for (int i = 0; i < cts.size(); i++) {
            Constraint constr = cts.get(i);
            constr.addHelpfulNames(helpfulConstrNames);
            constr.addToGraph(g, i + 1);
        }
        showGraph(makeEqualitiesUndirected(g), true, "Original Graph", highlightNodes);

        ArrayList<Set<String>> sccs = getVerticesToKeepJgraph(g, highlightNodes, Constraint.keepStrictEdges(cts));

        for (int i = 0; i < sccs.size(); i++) {
            filterKeepAndVisualize(g, sccs.get(i), highlightNodes, "SCC #" + i);
        }

        return sccs.size();
    }

    static String readFile(String path) throws IOException {
        byte[] encoded = Files.readAllBytes(Paths.get(path));
        return new String(encoded, Charset.defaultCharset());
    }

    public static void main(String[] args) throws IOException {
        System.out.println("args" + Arrays.toString(args));
        if (args.length != 1) {
            System.err.println(
                    "usage : java -jar DebugUniv.jar filename\n where filename contains the constraints, e.g. output of Print Universes");
            return;
        }
        DebugUnivInconst dbg = new DebugUnivInconst();
        String fileString = readFile(args[0]);
        dbg.showTopUnivs(fileString);
        dbg.debugUnivInconsistency(parseConstraints(fileString), new HashSet<String>());
    }
}