edu.usc.squash.Main.java Source code

Java tutorial

Introduction

Here is the source code for edu.usc.squash.Main.java

Source

/*
 *
 * Copyright (C) 2015 Mohammad Javad Dousti, Alireza Shafaei, and Massoud Pedram, SPORT lab,
 * University of Southern California. All rights reserved.
 *
 * Please refer to the LICENSE file for terms of use.
 *
*/

package edu.usc.squash;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Stack;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.GnuParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.jgrapht.graph.DefaultEdge;
import org.jgrapht.graph.SimpleDirectedGraph;

import edu.usc.squash.dfg.CalledModule;
import edu.usc.squash.dfg.DFG;
import edu.usc.squash.dfg.Module;
import edu.usc.squash.dfg.Operand;
import edu.usc.squash.dfg.Vertex;
import edu.usc.squash.parser.hfq.HFQParser;
import edu.usc.squash.schedule.Schedule;

public class Main {
    /* Squash input parameters */
    private static int k = 6;
    private static int physicalAncillaBudget = k * 100;
    private static int beta_pmd = 10;
    private static int alpha_int = 3;
    private static double gamma_memory = 0.2;
    private static String currentECC = "Steane";
    //private static final String currentECC = "Bacon-Shor";      

    private static String metisDir = "./metis";
    private static int gurobiTimeLimit = 120;

    private static String libraryPath = null;
    private static String hfqPath = null;

    private static int B_P = 0;

    public static void main(String[] args) {
        Stack<Module> modulesStack;
        Module module;

        if (parseInputs(args) == false) {
            System.exit(-1); //The input files do not exist
        }

        String separator = "----------------------------------------------";
        System.out.println("Squash v2.0");
        System.out.println(separator);
        long start = System.currentTimeMillis();

        // Parsing the input library
        Library library = QLib.readLib(libraryPath);
        library.setCurrentECC(currentECC);

        HashMap<String, Module> modules = parseQASMHF(library);
        Module mainModule = modules.get("main");

        //Finding max{A_L_i}
        int childModulesLogicalAncillaReq;
        int moduleAncillaReq;

        modulesStack = new Stack<Module>();

        modulesStack.add(mainModule);
        while (!modulesStack.isEmpty()) {
            module = modulesStack.peek();
            if (!module.isVisited() && module.isChildrenVisited()) {
                //Finding the maximum 
                childModulesLogicalAncillaReq = 0;
                for (Module child : module.getDFG().getModules()) {
                    childModulesLogicalAncillaReq = Math.max(childModulesLogicalAncillaReq, child.getAncillaReq());
                }
                moduleAncillaReq = module.getAncillaQubitNo() + childModulesLogicalAncillaReq;
                module.setAncillaReq(moduleAncillaReq);
                //            System.out.println("Module "+module.getName()+" requires "+moduleAncillaReq+" ancilla.");

                modulesStack.pop();
                module.setVisited();
            } else if (module.isVisited()) {
                modulesStack.pop();
            } else if (!module.isChildrenVisited()) {
                modulesStack.addAll(module.getDFG().getModules());
                module.setChildrenVisited();
            }
        }

        int totalLogicalAncilla = mainModule.getAncillaReq();

        System.out.println("A_L_i_max: " + totalLogicalAncilla);

        final int Q_L = mainModule.getDataQubitNo();

        /* 
         * In order traversal of modules
         */
        //Making sure all of the modules are unvisited
        for (Module m : modules.values()) {
            m.setUnvisited();
        }
        modulesStack = new Stack<Module>();

        modulesStack.add(mainModule);
        while (!modulesStack.isEmpty()) {
            module = modulesStack.peek();
            if (!module.isVisited() && module.isChildrenVisited()) {
                System.out.println(separator);

                mapModule(module, k, physicalAncillaBudget, totalLogicalAncilla, Q_L, beta_pmd, alpha_int,
                        gamma_memory, library);

                modulesStack.pop();
                module.setVisited();
            } else if (module.isVisited()) {
                modulesStack.pop();
            } else if (!module.isChildrenVisited()) {
                modulesStack.addAll(module.getDFG().getModules());
                module.setChildrenVisited();
            }
        }

        System.out.println(separator);
        double runtime = (System.currentTimeMillis() - start) / 1000.0;
        System.out.println("B_P: " + B_P);
        System.out.println("Total Runtime:\t" + runtime + " sec");
    }

    public static String getMetisDir() {
        return metisDir;
    }

    public static int getGurobiTimeLimit() {
        return gurobiTimeLimit;
    }

    public static void assertAncillaeRequirement(int k, Module module, int physicalAncillaBudget,
            int logicalAncillaBudget) {
        SimpleDirectedGraph<Vertex, DefaultEdge> QODG = module.getDFG().getDFG();
        int physMinAncilla = 0;

        for (Vertex v : QODG.vertexSet()) {
            if (v.isModule())
                continue;
            if (v.getAncillaQubitNo() > physMinAncilla)
                physMinAncilla = v.getAncillaQubitNo();
        }
        //Checking to see if the allocated number of ancillae were sufficient
        if (physMinAncilla > (physicalAncillaBudget / k)) {
            System.err.println("Not enough physical ancilla is allocated! At least " + physMinAncilla
                    + " ancilla per core are neaded!");
            System.exit(-1);
        }

        //      int minLogicalAncillaReq = 0;
        //
        //      for (Module m : module.getDFG().getModules()) {
        //         if (m.getAncillaQubitNo() > minLogicalAncillaReq)
        //            minLogicalAncillaReq = m.getAncillaQubitNo(); 
        //      }
        //
        //      if (module.getAncillaQubitNo() + minLogicalAncillaReq > logicalAncillaBudget){
        //         System.out.flush();
        //         System.err.flush();
        //         System.err.println("Not enough logical ancilla is allocated! At least "+ (module.getAncillaQubitNo() + minLogicalAncillaReq)+
        //               " ancilla are neaded for module "+module.getName()+" but only "+logicalAncillaBudget+" provided.");
        //         System.exit(-1);
        //      }
    }

    private static void print_usage(Options options) {
        // automatically generate the help statement
        HelpFormatter formatter = new HelpFormatter();
        formatter.setWidth(90);
        formatter.printHelp("squash", "Squash v2: A hierarchical scalable considering ancilla sharing", options, "",
                true);
    }

    private static boolean parseInputs(String[] args) {
        Options options = new Options();

        options.addOption("k", "cores", true, "Total number of cores (Default: " + k + ")");
        options.getOption("k").setArgName("number");

        options.addOption("p", "physical", true,
                "Physical ancilla budget (Default: " + physicalAncillaBudget + ")");
        options.getOption("p").setArgName("number");

        options.addOption("b", "beta_pmd", true, "Beta_PMD (Default: " + beta_pmd + ")");
        options.getOption("b").setArgName("number");

        options.addOption("a", "alpha_int", true, "Alpha_int (Default: " + alpha_int + ")");
        options.getOption("a").setArgName("number");

        options.addOption("g", "gamma_mem", true, "Gamma_memory (Default: " + gamma_memory + ")");
        options.getOption("g").setArgName("number");

        options.addOption("e", "ecc", true, "Error correcting code (Default: " + currentECC + ")");
        options.getOption("e").setArgName("type");

        options.addOption("q", "hf-qasm", true, "HF-QASM input file");
        options.getOption("q").setArgName("file");

        options.addOption("l", "lib", true, "Library file");
        options.getOption("l").setArgName("file");

        options.addOption("m", "metis", true, "Metis directory (Default: " + metisDir + ")");
        options.getOption("m").setArgName("path");

        options.addOption("t", "timeout", true, "Gurobi timelimit for binding (Default: " + gurobiTimeLimit + "s)");
        options.getOption("t").setArgName("number");

        options.addOption("h", "help", false, "Shows this help menu");

        CommandLineParser parser = new GnuParser();
        CommandLine cmd = null;
        try {
            cmd = parser.parse(options, args);
        } catch (ParseException e) {
            System.err.println(e.getMessage());
            System.exit(-1);
        }

        if (!cmd.hasOption("lib") || !cmd.hasOption("hf-qasm") || cmd.hasOption("help")) {
            //TODO: remove this
            if (libraryPath == null || hfqPath == null || cmd.hasOption("help")) {
                print_usage(options);
                return false;
            }
        }

        if (cmd.hasOption("lib")) {
            libraryPath = cmd.getOptionValue("lib");
            if (!new File(libraryPath).exists()) {
                System.err.println("Library file " + hfqPath + " does not exist.");
                return false;
            }
        }

        if (cmd.hasOption("hf-qasm")) {
            hfqPath = cmd.getOptionValue("hf-qasm");
            if (!new File(hfqPath).exists()) {
                System.err.println("HF-QASM file " + hfqPath + " does not exist.");
                return false;
            }
        }

        if (cmd.hasOption("cores")) {
            k = Integer.parseInt(cmd.getOptionValue("cores"));
        }

        if (cmd.hasOption("timelimit")) {
            gurobiTimeLimit = Integer.parseInt(cmd.getOptionValue("timelimit"));
        }

        if (cmd.hasOption("physical")) {
            physicalAncillaBudget = Integer.parseInt(cmd.getOptionValue("physical"));
        }

        if (cmd.hasOption("beta_pmd")) {
            beta_pmd = Integer.parseInt(cmd.getOptionValue("beta_pmd"));
        }

        if (cmd.hasOption("alpha_int")) {
            alpha_int = Integer.parseInt(cmd.getOptionValue("alpha_int"));
        }

        if (cmd.hasOption("gamma_memory")) {
            gamma_memory = Integer.parseInt(cmd.getOptionValue("gamma_memory"));
        }
        if (cmd.hasOption("ecc")) {
            currentECC = cmd.getOptionValue("ecc");
        }

        if (cmd.hasOption("metis")) {
            metisDir = cmd.getOptionValue("metis");
        }

        return true;
    }

    public static void mapModule(Module module, int k, int b_qrcr, int logicalAncillaBudget, final int Q_L,
            int beta_pmd, int alpha_int, double gamma_memory, Library library) {
        DFG dfg = module.getDFG();
        System.out.println("Mapping module " + module.getName() + "...");

        //Checking if the physical and logical budget is enough
        assertAncillaeRequirement(k, module, b_qrcr, logicalAncillaBudget);

        /*
         * Partitioning and picking the highest possible part no. 
         * which is smaller than k
         */
        Partitioner partitioner = new Partitioner(dfg, library);
        try {
            //         partitioner.partition(k);
            int parts = partitioner.partition(k);
            System.out.println("Partition count: " + parts);
        } catch (Exception e) {
            e.printStackTrace();
        }

        for (Module m : module.getDFG().getModules()) {
            if (m.getDFG().getCoreUsage().size() > k)
                k = m.getDFG().getCoreUsage().size();
        }

        if (k == 1) {
            module.getDFG().useSingleCore();
        }

        System.out.println("K is selected as " + k + ".");

        /*
         * Building and characterizing a ReQup Architecture
         */

        ReQuP requp = new ReQuP(module, k, b_qrcr, logicalAncillaBudget, Q_L, beta_pmd, alpha_int, gamma_memory,
                dfg.getDFG(), library, partitioner.getASAPDirectory());

        module.setRequp(requp);
        B_P = Math.max(B_P, requp.getTotalUsedPhsicalAncilla());

        /*
         * Binding
         */
        if (k > 1) { //otherwise no binding is required.
            Binder.bind(k, requp.getInterCoreRoutingDelay(), dfg.getDFG(), requp);
        }

        Schedule.listScheduling(module, k, b_qrcr, logicalAncillaBudget, requp.getInterCoreRoutingDelay(), dfg);

        System.out.println("Latency:\t" + module.getDelay() + " us");
    }

    private static HashMap<String, Module> parseQASMHF(Library library) {
        HFQParser hfqParser = null;
        /*
         * Pass 1: Getting module info
         */
        try {
            hfqParser = new HFQParser(new FileInputStream(hfqPath));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        HashMap<String, Module> moduleMap = hfqParser.parse(library, true, null);

        /* 
         * In order traversal of modules
         */

        ArrayList<CalledModule> modulesList = new ArrayList<CalledModule>();
        modulesList.add(new CalledModule(moduleMap.get("main"), new ArrayList<String>()));
        while (!modulesList.isEmpty()) {
            Module module = modulesList.get(0).getModule();

            if (!module.isVisited()) {
                module.setVisited();

                ArrayList<CalledModule> calledModules = module.getChildModules();
                modulesList.addAll(calledModules);
                for (CalledModule calledModule : calledModules) {
                    Module childModule = calledModule.getModule();
                    for (int i = 0; i < calledModule.getOps().size(); i++) {
                        Operand operand = childModule.getOperand(i);
                        if (operand.isArray() && operand.getLength() == -1) {
                            operand.setLength(module.getOperandLength(calledModule.getOps().get(i)));
                        }
                    }
                }
            }
            modulesList.remove(0);
        }

        /*
         * Pass 2: Making hierarchical QMDG
         */
        try {
            hfqParser = new HFQParser(new FileInputStream(hfqPath));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        HashMap<String, Module> modules = hfqParser.parse(library, false, moduleMap);

        return modules;
    }

}