Exemple #1
0
    def compute_from_smt(self, smt):
        assigns = self.exprmgr.mkBoolConst(True)
        exe = Execution()

        for relation in self.relations:
            assign = self.symboltable.lookup(relation)
            value = smt.getValue(assign)
            rel = self.__relation_from_formula(relation, value)
            assert (rel is not None)

            exe.set_relation_by_name(relation, rel)

            if relation in self.blocking_relations:
                assign = self.exprmgr.mkExpr(EQUAL, assign, value)
                assigns = self.exprmgr.mkExpr(AND, assigns, assign)

        for variable in self.variables:
            assign = self.symboltable.lookup(variable)
            value = smt.getValue(assign).toString()
            exe.add_condition(variable, value)

            assign = self.exprmgr.mkExpr(EQUAL, assign, smt.getValue(assign))
            assigns = self.exprmgr.mkExpr(AND, assigns, assign)

        blocking = self.exprmgr.mkExpr(NOT, assigns)

        Logger.log("Blocking: %s" % (blocking.toString()), 2)
        self.models.append(exe)
        self.write_models(self.models, False)

        return ([blocking], exe)
Exemple #2
0
 def compute_from_sharedobjs(self, shared_objs):
     executions = Executions()
     executions.executions = shared_objs
     assertions = self.encoder.print_assert_neg_execs(
         executions, self.blocking_relations)
     Logger.log("Blocking: \n%s" % ("\n".join(assertions)), 2)
     return "\n" + ("\n".join(assertions))
Exemple #3
0
    def __compute_models(self,
                         model,
                         solver,
                         num,
                         blocking_manager,
                         constraints=None,
                         shared_objects=None):
        if constraints:
            model += "\n" + constraints

        assertions = blocking_manager.compute_from_sharedobjs(shared_objects)
        model += "\n" + assertions

        num_sols = 0
        while True:
            if (num != -1) and (num_sols >= num):
                break
            ret = self.solve_one(model, solver)
            self.__clean_files()
            if ret is None:
                return (shared_objects, 0)
            num_sols += 1
            (bclauses, shared_obj) = blocking_manager.compute_from_smt(ret)
            Logger.msg(".", 0, True, 0)

            if shared_obj not in shared_objects:
                shared_objects.append(shared_obj)
            else:
                if constraints is not None:
                    return (shared_objects, 2)

            model += bclauses

        return (shared_objects, 1)
Exemple #4
0
    def prune_not_eq(self, ao_execs, executions, model, program, threads):
        self.c4vexecsmanager.preload = False
        beparser = BeParser()
        eq_progs = []
        equivalent_AOs = []
        events_dic = dict([(x.name, x) for x in program.get_events()])

        if threads > 1:
            valid_aos = self.__check_all_mt(model, ao_execs, executions,
                                            threads)
        else:
            valid_aos = self.__check_all(model, ao_execs, executions)

        for exe in valid_aos:
            rel = Relation(AO)
            rel.tuples = [(events_dic[str(x[0])], events_dic[str(x[1])])
                          for x in exe.get_AO().tuples]
            exe.set_AO(rel)
            exe.program = program
            equivalent_AOs.append(exe)
            program = beparser.program_from_execution(exe)
            eq_progs.append(program)

        Logger.log(" DONE", 1)
        if Logger.level(1):
            for el in equivalent_AOs:
                Logger.log("EQUIVALENT: %s" % el.get_AO(), 1)

        return eq_progs
Exemple #5
0
    def compute_from_smt(self, smt):
        AlloyValidExecsModelsManager.id_blocking += 1

        exe = self.__generate_execution(smt)
        blocking = []
        for rel in self.blocking_relations:
            tuples = self.__extract_tuples(self.__relname_mapping()[rel], smt)
            if len(tuples[0]) == 0:
                blocking.append("(no %s.rel)" %
                                (self.__relname_mapping()[rel]))
            else:
                btup = []
                for tup in tuples:
                    btup.append(" -> ".join(tuple(tup)))
                blocking.append("%s.rel = %s" %
                                (self.__relname_mapping()[rel], " + ".join(
                                    ["{(%s)}" % x for x in btup])))

        for var in self.variables:
            value = self.__get_condition(smt, var)
            if value is not None:
                blocking.append("(%s.value = %s)" % (var, value))
                exe.add_condition(var, value)

        blocking = "fact block_smt_%s {not (%s)}\n" % (
            AlloyValidExecsModelsManager.id_blocking, " and ".join(blocking))

        Logger.log("Blocking: %s" % (blocking), 2)

        self.models.append(exe)
        self.write_models(self.models, False)

        return (blocking, exe)
Exemple #6
0
    def solve_all_cvc4(self, model, program=None, nexecs=-1, threads=1):
        self.cvc4_vexecsmanager.program = program
        if program.has_conditions:
            self.cvc4_vexecsmanager.set_additional_variables(
                program.get_conditions())

        timer = Logger.start_timer("CVC4 solve all")
        ret = self.c4solver.solve_allsmt(model, self.cvc4_vexecsmanager,
                                         nexecs, threads)
        Logger.stop_timer(timer)
        return len(ret)
Exemple #7
0
 def solve_all_alloy(self, model, program=None, nexecs=-1, threads=1):
     self.alloy_vexecsmanager.program = program
     if program.has_conditions:
         self.alloy_vexecsmanager.set_additional_variables(
             program.get_conditions())
     model += self.alloyencoder.print_run_condition(program)
     timer = Logger.start_timer("Alloy solve all")
     ret = self.alloysolver.solve_allsmt(model, self.alloy_vexecsmanager,
                                         nexecs, threads)
     Logger.stop_timer(timer)
     return len(ret)
Exemple #8
0
    def compute_from_smt(self, smt):
        assigns = self.exprmgr.mkBoolConst(True)
        model = []
        for varstr in self.labelling_vars:
            assign = self.symboltable.lookup(varstr)
            value = smt.getValue(assign)
            model.append(
                "%s%s" %
                ("" if value.getConstBoolean() else "~", assign.toString()))

            assign = self.exprmgr.mkExpr(EQUAL, assign, smt.getValue(assign))
            assigns = self.exprmgr.mkExpr(AND, assigns, assign)

        blocking = self.exprmgr.mkExpr(NOT, assigns)
        Logger.log("Blocking: %s" % (blocking.toString()), 2)
        return ([blocking], "(%s)" % " & ".join(model))
Exemple #9
0
    def compute_from_smt(self, model):
        AlloyConstraintAnalyzerManager.id_blocking += 1

        blocking = []
        bddmodel = []
        for var in self.labelling_vars:
            value = self.__get_condition(model, var)
            if value is not None:
                blocking.append("(%s.value = %s)" % (var, value))
                bddmodel.append("(%s%s)" %
                                ("~" if value == "TRUE" else "", var))

        blocking_str = "fact block_smt_%s {not (%s)}\n" % (
            AlloyConstraintAnalyzerManager.id_blocking, " and ".join(blocking))
        Logger.log("Blocking: %s" % (blocking_str), 2)
        return (blocking_str, (" and ".join(blocking), " & ".join(bddmodel)))
Exemple #10
0
    def solutions_separators(self):
        if not self.program:
            return []

        ao_set = [(x.name, y.name) for x in self.program.get_events()
                  for y in self.program.get_events() if x != y]
        ao_cons = [
            self.encoder.assert_formula("(AO [%s, %s])" % (x)) for x in ao_set
        ]

        Logger.msg("(%s)" % len(ao_cons), 0)

        if self.shuffle_constraints:
            random.shuffle(ao_cons)

        return ao_cons
Exemple #11
0
 def __print_models(self, models):
     msg = " -> Found %s solution%s" % (len(models),
                                        "" if len(models) == 1 else "s")
     if models == ["()"]:
         Logger.log("VALID\n", 0)
     elif len(models) == 0:
         Logger.log("FALSE\n", 0)
     else:
         Logger.log(msg, 0)
         Logger.log("%s\n" % (" | \n".join(models)), 0)
Exemple #12
0
    def solve_allsmt(self, model, blocking_manager, num_sols=-1, num_t=1):
        num_t = 1
        self.__init_solvers(num_t)
        pre_objs = blocking_manager.load_models()
        Logger.msg("." * len(pre_objs), 0, True, 0)
        ret = None
        if num_t > 1:
            rb_cons = blocking_manager.solutions_separators()
            num_t = min(len(rb_cons), num_t)
            if num_t < 3:
                # Multithread is not necessary
                ret = self.__solve_nsat(model, num_sols, blocking_manager,
                                        pre_objs)
            else:
                with Manager() as manager:
                    shared_objs = manager.list([])
                    for el in pre_objs:
                        shared_objs.append(el)
                    rb_cons = manager.list(rb_cons)

                    threads = []
                    for i in range(num_t - 1):
                        process = Process(target=self.__solve_nsat,
                                          args=(model, -1, blocking_manager,
                                                shared_objs, i, num_t - 1,
                                                rb_cons))
                        threads.append(process)
                        process.start()

                    shared_objs = self.__solve_nsat(model, num_sols,
                                                    blocking_manager,
                                                    shared_objs, 0)

                    for thread in threads:
                        thread.terminate()

                    ret = list(shared_objs)
        else:
            ret = self.__solve_nsat(model, num_sols, blocking_manager,
                                    pre_objs)

        self.__quit_solvers()
        return ret
Exemple #13
0
 def solve_one(self, model, solver):
     if Logger.level(3):
         linenum = 0
         for line in model.split("\n"):
             linenum += 1
             Logger.log("%s: %s" % (linenum, line), 3)
     solver.stdin.write(('%s\nreset\n' % (model)).encode())
     solver.stdin.flush()
     out = ""
     while True:
         line = solver.stdout.readline().decode()
         out += line
         if line in ["sat\n", "unsat\n"]:
             break
     out = out.split("\n")
     Logger.log("Solver: %s" % out[0], 2)
     if out[-2] == "sat":
         return out
     else:
         return None
Exemple #14
0
    def solutions_separators(self):
        if not self.program:
            return []

        rf = True

        cr = self.encoder.get_compatible_reads(self.program)
        rb_cons = [
            self.encoder.assert_formula("(RBF %s)" % (x)) for x in cr[1]
        ]

        if rf:
            rb_cons += [
                self.encoder.assert_formula("(RF %s)" % (x)) for x in cr[0]
            ]

        Logger.msg("(%s)" % len(rb_cons), 0)

        if self.shuffle_constraints:
            random.shuffle(rb_cons)

        return rb_cons
Exemple #15
0
    def user_defined_analyses(self, mmodels, nmodels):
        config = configparser.ConfigParser()
        config.optionxform = str

        with open(UNMATCHED_FILE, "r") as f:
            config.read_string(u"" + f.read())

        analyses = []

        for value in config:
            if value == DEFAULT: continue
            analysis = config[value]
            analyses.append((analysis[DESCRIPTION], analysis[FORMULA]))

        for analysis in analyses:
            Logger.log(analysis[0], 0)
            formula = analysis[1].replace("unmatched", "{u}").replace(
                "matched", "{m}").replace("!", "~")
            formula = formula.format(m=" | ".join(mmodels),
                                     u=" | ".join(nmodels))
            formula = self.bsolver.simplify(formula, True)
            self.__print_models(formula)
Exemple #16
0
    def __process_quantifier_int(self, formula, set_dict, set_type_dict, sup):
        cond1 = False
        cond2 = False
        cond3 = False

        quantifier = None

        if type(formula) == list:
            quantifier = self.FORALL if (self.FORALL in formula[0]) else \
                         self.EXISTS if (self.EXISTS in formula[0]) else \
                         self.BIGUNION if (self.BIGUNION in formula[0]) else \
                         self.BIGSUM if (self.BIGSUM in formula[0]) else None
            cond1 = quantifier is not None
            if (len(formula) > 1):
                cond2 = ((len(formula[1]) > 0) and (" IN " in formula[1][0]))
                cond3 = (" IN " not in self.__print_formula(formula[2:]))

        if cond1 and cond2 and cond3:
            Logger.log(
                "%% Processing quantifier %s: %s" %
                (quantifier, self.__print_formula(formula)), 2)
            if self.expand_sets or (quantifier
                                    == self.BIGUNION) or (quantifier
                                                          == self.BIGSUM):
                value = self.__sub_quantifier_expand(formula, quantifier,
                                                     set_dict)
            else:
                value = self.__sub_quantifier(formula, quantifier,
                                              set_type_dict)
            sup[0] = True
            return value
        else:
            if type(formula) == list:
                for i in range(len(formula)):
                    formula[i] = self.__process_quantifier_int(
                        formula[i], set_dict, set_type_dict, sup)

        return formula
Exemple #17
0
 def solve_all_synth(self, model, program, threads):
     timer = Logger.start_timer("CVC4 intersect")
     (ao_execs,
      executions) = self.find_all_intersect(model, program, threads)
     Logger.stop_timer(timer)
     timer = Logger.start_timer("CVC4 prune equivalent")
     ret = self.prune_not_eq(ao_execs, executions, model, program, threads)
     Logger.stop_timer(timer)
     return ret
Exemple #18
0
 def solve_all_synth_hybrid(self, cvc4model, alloymodel, program, threads):
     timer = Logger.start_timer("Alloy intersect")
     (ao_execs, executions) = self.alloy_synth.find_all_intersect(
         alloymodel, program, 1)
     Logger.stop_timer(timer)
     timer = Logger.start_timer("CVC4 prune equivalent")
     ret = self.cvc4_synth.prune_not_eq(ao_execs, executions, cvc4model,
                                        program, threads)
     Logger.stop_timer(timer)
     return ret
Exemple #19
0
def unmatched_analysis(config):
    analyzer = ConstraintsAnalyzer()
    analyzer.set_models_file(config.models)
    analyzer.set_outputs_file(config.outputs)

    Logger.log("\n** Unmatched Outputs Analysis **", 0)

    config.unmatched = True

    if not config.defines:
        config.defines = ""
    config.defines += CONS_LABELLING

    program = parse_program(config)

    Logger.msg("Generating model... ", 0)

    if config.use_alloy:
        strmodel = generate_alloy_model(config, program)
    else:
        strmodel = generate_cvc_model(config, program)

    Logger.log("DONE", 0)

    if config.only_model:
        return 0

    if (config.force_solving):
        del_file(config.outputs)

    if config.use_alloy:
        analyzer.analyze_constraints_alloy(program, \
                                           strmodel, \
                                           config.jsengine, \
                                           config.runs, \
                                           config.threads, \
                                           config.outprogram+".js")
    else:
        analyzer.analyze_constraints_cvc4(program, \
                                          strmodel, \
                                          config.jsengine, \
                                          config.runs, \
                                          config.threads, \
                                          config.outprogram+".js")
    return 0
Exemple #20
0
    def __compute_models(self,
                         model,
                         num,
                         blocking_manager,
                         constraints=None,
                         shared_objects=None):
        opts = Options()
        opts.setInputLanguage(CVC4.INPUT_LANG_CVC4)

        exit_with_unknown = False

        if shared_objects is None:
            shared_objects = []

        exprmgr = ExprManager(opts)

        smt = SmtEngine(exprmgr)
        smt.setOption("produce-models", SExpr(True))
        smt.setOption("fmf-bound", SExpr(True))
        smt.setOption("macros-quant", SExpr(True))
        smt.setOption("finite-model-find", SExpr(True))
        #        smt.setOption("repeat-simp", SExpr(True))
        #        smt.setOption("check-models", SExpr(True))
        #        smt.setOption("full-saturate-quant", SExpr(True))
        smt.setOption("incremental", SExpr(True))

        ind = 0

        assertions = blocking_manager.compute_from_sharedobjs(shared_objects)
        model = model + assertions

        if constraints:
            model += "\n%s;" % (constraints)

        parserbuilder = ParserBuilder(exprmgr, "", opts)
        parserbuilder.withStringInput(model)
        parser = parserbuilder.build()

        symboltable = parser.getSymbolTable()

        blocking_manager.exprmgr = exprmgr
        blocking_manager.symboltable = symboltable

        while True:
            cmd = parser.nextCommand()
            if not cmd: break
            cmd.invoke(smt)

        while True:
            checksat = CheckSatCommand()
            checksat.invoke(smt)

            sat = checksat.getResult().isSat() == 1
            unk = checksat.getResult().isUnknown()
            uns = (not sat) and (not unk)

            Logger.log("sat: %s, uns: %s, unk: %s" % (sat, uns, unk), 2)

            exitcond = (not sat) if exit_with_unknown else uns

            if exitcond:
                return (shared_objects, 0)

            (bclauses, shared_obj) = blocking_manager.compute_from_smt(smt)

            Logger.log("%s" % str(shared_obj), 2)

            if shared_obj not in shared_objects:
                shared_objects.append(shared_obj)
            else:
                if constraints is not None:
                    return (shared_objects, 2)

            for bclause in bclauses:
                assertion = AssertCommand(bclause)
                assertion.invoke(smt)

            Logger.msg(".", 0, constraints is None, 0)

            ind += 1
            if (num != -1) and (ind >= num):
                return (shared_objects, 1)

        return (None, -1)
Exemple #21
0
    def analyze_constraints(self, program, model, jsengine, runs, threads,
                            jsprogram, use_alloy):
        matched = None
        unmatched = None

        config = Config()
        config.command = jsengine
        config.input_file = jsprogram
        config.threads = threads
        config.number = runs
        config.silent = True
        config.models = True

        if use_alloy:
            labelling_vars = [y[2] for y in [x.split(" ") for x in model.split("\n") if len(x.split(" "))>2] \
                              if y[2][:len(LABELLING_VAR_PREF)] == LABELLING_VAR_PREF]
        else:
            labelling_vars = [x.split(" ")[0] for x in model.split("\n") \
                              if x[:len(LABELLING_VAR_PREF)] == LABELLING_VAR_PREF]

        if len(labelling_vars) == 0:
            Logger.error("No labelling vars defined")
            return None

        if use_alloy:
            self.al_consamanager.labelling_vars = labelling_vars
        else:
            self.c4_consamanager.labelling_vars = labelling_vars

        (matched, unmatched) = self.__load_outputs(config.number, self.outfile,
                                                   jsengine)

        if (matched is None) and (unmatched is None):
            timer = Logger.start_timer("Run Litmus")
            (matched, unmatched) = run_litmus(config)
            Logger.stop_timer(timer)
            self.__save_outputs(config.number, self.outfile, jsengine, matched,
                                unmatched)

        timer = Logger.start_timer("Analyze output")

        parser = BeParser()
        mexecs = parser.executions_from_string("\n".join(matched), program)
        uexecs = parser.executions_from_string("\n".join(unmatched), program)

        Logger.log(" -> Found %s matched models" % (len(matched)), 0)
        Logger.log(" -> Found %s unmatched models" % (len(unmatched)), 0)

        if len(unmatched) == 0:
            Logger.error("No unmatched models")
            Logger.stop_timer(timer)
            return None

        rels = [x for x in RELATIONS if x != AO]

        matched = self.al_encoder.print_assert_exl_execs(mexecs, rels) if use_alloy else \
                  self.c4_encoder.print_assert_exl_execs(mexecs, rels)
        unmatched = self.al_encoder.print_assert_exl_execs(uexecs, rels) if use_alloy else \
                    self.c4_encoder.print_assert_exl_execs(uexecs, rels)

        objs = []
        Logger.log("\nMatched models analysis", 0)
        Logger.msg("Solving... ", 0)

        if use_alloy:
            vmodel = "\n".join([
                model, matched,
                self.al_encoder.print_run_condition(program, True)
            ])
            objs = self.al_solver.compute_models(vmodel, self.al_consamanager,
                                                 objs)
            mmodels = " | ".join([x[1] for x in objs])
        else:
            vmodel = "%s\n%s" % (model, matched)
            objs = self.c4_solver.compute_models(vmodel, self.c4_consamanager,
                                                 objs)
            mmodels = " | ".join(objs)

        Logger.log(" DONE", 0)
        mmodels = self.bsolver.simplify(mmodels, True)
        self.__print_models(mmodels)

        objs = []
        Logger.log("Unmatched models analysis", 0)
        Logger.msg("Solving... ", 0)

        if use_alloy:
            vmodel = "\n".join([
                model, unmatched,
                self.al_encoder.print_run_condition(program, True)
            ])
            objs = self.al_solver.compute_models(vmodel, self.al_consamanager,
                                                 objs)
            nmodels = " | ".join([x[1] for x in objs])
        else:
            vmodel = "%s\n%s" % (model, unmatched)
            objs = self.c4_solver.compute_models(vmodel, self.c4_consamanager,
                                                 objs)
            nmodels = " | ".join(objs)

        Logger.log(" DONE", 0)
        nmodels = self.bsolver.simplify(nmodels, True)
        self.__print_models(nmodels)

        Logger.log("Difference analysis (exist support(matched) in unmatched)",
                   0)
        diffmodels = self.bsolver.support_exist(" | ".join(mmodels),
                                                " | ".join(nmodels), True)
        self.__print_models(diffmodels)

        self.user_defined_analyses(mmodels, nmodels)

        Logger.stop_timer(timer)
        return (mmodels, nmodels, diffmodels)
Exemple #22
0
    def __solve_nsat(self,
                     model,
                     n,
                     blocking_manager,
                     shared_objs=None,
                     id_thread=None,
                     total=None,
                     constraints=None):
        applying_cons = None

        if shared_objs is None:
            shared_objs = []
        is_multithread = id_thread is not None
        is_master = constraints is None

        if is_multithread:
            if is_master:
                process = self.alloy_processes[0]
            else:
                process = self.alloy_processes[id_thread + 1]
        else:
            process = self.alloy_processes[0]

        if not is_multithread or is_master:
            self.__clean_files()

        if constraints is not None:
            applying_cons = constraints[id_thread]

        if not is_multithread:
            (sol, ret) = self.__compute_models(model, process, n,
                                               blocking_manager, applying_cons,
                                               shared_objs)

            for el in sol:
                if el not in shared_objs:
                    shared_objs.append(el)

            blocking_manager.write_models(shared_objs, ret == 0)
            return sol

        sol = None
        prvsolsize = 0
        solsize = 0
        while (solsize < n) or (n == -1):
            prvsolsize = solsize
            (sol, ret) = self.__compute_models(model, process, 1,
                                               blocking_manager, applying_cons,
                                               shared_objs)

            for el in sol:
                if el not in shared_objs:
                    shared_objs.append(el)
            solsize = len(sol)

            if is_master:
                blocking_manager.write_models(shared_objs, ret == 0)

            if (self.verbosity > 0) and is_multithread and is_master:
                if ((solsize - prvsolsize) > 1):
                    gain = (solsize - prvsolsize) - 1
                    Logger.msg("+%s%s" % (gain, "." * (gain)), 0, True, 0)

            if not is_master:
                if ret == 0:  #UNSAT
                    if id_thread >= len(constraints) - 1:
                        break
                    Logger.msg("d", 0)
                    constraints[id_thread] = constraints[-1]
                    del (constraints[-1])
                    applying_cons = constraints[id_thread]
                    continue

                if ret == 2:  # Not interesting constraint
                    Logger.msg("s", 0)

                    if len(constraints) > total:
                        tmp = constraints[id_thread]
                        constraints[id_thread] = constraints[-1]
                        constraints[-1] = tmp
                        constraints[total:] = constraints[total + 1:] + [
                            constraints[total]
                        ]
                        applying_cons = constraints[id_thread]

            if ret == 0:
                break

        return shared_objs
Exemple #23
0
def synth_program(config):
    analyzer = EquivalentExecutionSynthetizer()
    analyzer.set_models_file(config.models)

    Logger.log("\n** Equivalent Programs Synthesis **", 0)

    config.synth = True

    if not config.defines:
        config.defines = ""
    config.defines += RELAX_AO

    program = parse_program(config)
    if program.has_conditions():
        Logger.msg("Program synthesis does not support conditional programs",
                   0)
        return 0

    Logger.msg("Generating relaxed SMT model... ", 0)
    if config.use_alloy or config.hybrid:
        strmodel_alloy = generate_alloy_model(config, program)

    if not config.use_alloy or config.hybrid:
        strmodel_cvc4 = generate_cvc_model(config, program)
    Logger.log("DONE", 0)

    if config.only_model:
        return 0

    Logger.msg("Solving... ", 0)

    if config.use_alloy:
        programs = analyzer.solve_all_synth_alloy(strmodel_alloy, program,
                                                  config.threads)
    else:
        if config.hybrid:
            programs = analyzer.solve_all_synth_hybrid(strmodel_cvc4,
                                                       strmodel_alloy, program,
                                                       config.threads)
        else:
            programs = analyzer.solve_all_synth_cvc(strmodel_cvc4, program,
                                                    config.threads)
    totmodels = len(programs)

    Logger.log(" DONE", 0)

    if totmodels > 0:
        Logger.log(
            " -> Found %s equivalent program%s" %
            (totmodels, "" if totmodels == 1 else "s"), 0)
    else:
        Logger.log(" -> No viable equivalent programs found", 0)

    Logger.msg("Generating equivalent programs... ", 0)

    printer = PrintersFactory.printer_by_name(BePrinter.get_name())
    filename = (config.inputfile.split("/")[-1]).split(".")[0]

    for i in range(len(programs)):
        with open(config.eqprogs % (filename, str(i + 1)), "w") as eqprog:
            eqprog.write(printer.print_program(programs[i]))

    Logger.log("DONE", 0)

    Logger.log("", 1)

    Logger.log("** Original Program: **\n", 1)
    Logger.log(printer.print_program(program), 1)

    for program in programs:
        Logger.log(
            "** Equivalent Program %s: **\n" % (programs.index(program) + 1),
            1)
        Logger.log(printer.print_program(program), 1)

    return 0
Exemple #24
0
    def find_all_intersect(self, model, program, threads):
        self.c4vexecsmanager.program = program
        executions = Executions()
        executions.executions = self.c4vexecsmanager.load_models()
        self.c4vexecsmanager.preload = False

        vmodel = model + "\n" + self.c4_encoder.print_general_AO(program)
        qupre = QuantPreprocessor()
        qupre.set_expand_sets(True)
        vmodel = qupre.preprocess_from_string(vmodel)
        self.c4vexecsmanager.blocking_relations = [AO]
        ao_execs = []
        for models_blocking in [[RBF]]:
            assertions = self.c4_encoder.print_assert_exl_execs(
                executions, models_blocking)
            vmodel += "\n%s\n" % assertions
            execs = self.c4_solver.solve_allsmt(
                vmodel, self.c4vexecsmanager, -1,
                threads if ao_execs == [] else 1)
            ao_execs += [x for x in execs if x not in ao_execs]
            self.c4vexecsmanager.prevmodels = ao_execs
            Logger.msg(" ", 0)
        self.c4vexecsmanager.prevmodels = None

        Logger.log(" -> Found %s possible candidates" % (len(ao_execs)), 1)
        Logger.msg("Checking correctness... ", 1)

        if Logger.level(1):
            Logger.msg("\n", -1)
            for el in ao_execs:
                Logger.log("INTERSECTING: %s" % el.get_AO(), 1)

        return (ao_execs, executions)
Exemple #25
0
    def find_all_intersect(self, model, program, threads):
        run_condition = self.alloy_encoder.print_run_condition(program)
        self.allvexecsmanager.program = program
        executions = Executions()
        executions.executions = self.allvexecsmanager.load_models()
        self.allvexecsmanager.preload = False

        vmodel = "\n".join(
            [model, self.alloy_encoder.print_general_AO(program)])
        self.allvexecsmanager.blocking_relations = [AO]
        ao_execs = []
        for models_blocking in [[RBF]]:
            assertions = self.alloy_encoder.print_assert_exl_execs(
                executions, models_blocking)
            vmodel += "\n%s\n" % assertions
            execs = self.alloy_solver.solve_allsmt(
                vmodel + run_condition, self.allvexecsmanager, -1,
                threads if ao_execs == [] else 1)
            ao_execs += [x for x in execs if x not in ao_execs]
            self.allvexecsmanager.prevmodels = ao_execs
            Logger.msg(" ", 0)
        self.allvexecsmanager.prevmodels = None

        Logger.log(" -> Found %s possible candidates" % (len(ao_execs)), 1)
        Logger.msg("Checking correctness... ", 1)

        if Logger.level(1):
            Logger.msg("\n", -1)
            for el in ao_execs:
                Logger.log("INTERSECTING: %s" % el.get_AO(), 1)

        return (ao_execs, executions)
Exemple #26
0
def analyze_program(config):
    config.generate_filenames()

    Logger.log("\n** Program Analysis **", 0)

    Logger.msg("Generating bounded execution... ", 0)
    program = parse_program(config)
    Logger.log("DONE", 0)

    Logger.msg("Generating model... ", 0)
    if config.use_alloy:
        strmodel = generate_alloy_model(config, program)
    else:
        strmodel = generate_cvc_model(config, program)
    Logger.log("DONE", 0)

    if config.only_model:
        return 0

    if (not config.skip_solving):
        Logger.msg("Solving... ", 0)

    totmodels = solve(config, program, strmodel)

    if (not config.skip_solving):
        Logger.log(" DONE", 0)

    if totmodels > 0:
        Logger.log(
            " -> Found %s possible model%s" %
            (totmodels, "" if totmodels == 1 else "s"), 0)
    else:
        Logger.log(" -> No viable executions found", 0)

    # Generation of the JS litmus test #
    pprinter = PrintersFactory.printer_by_name(config.jsprinter)
    dprinter = PrintersFactory.printer_by_name(DotPrinter().get_name())
    dprinter.set_printing_relations(config.printing_relations)

    prefix = config.prefix
    params = program.get_params()
    models = config.models
    for idparam in range(program.param_size()):

        if program.params:
            config.prefix = "%sparam%03d/" % (prefix, idparam + 1)
            config.generate_filenames()
            program.apply_param(dict(params[idparam]))

            if config.verbosity > 0:
                conf = params[idparam]
                pconf = ["%s=\"%s\"" % (x[0], x[1]) for x in conf]
                Logger.log(
                    "\nParameter configuration (%03d): %s" %
                    (idparam + 1, (", ".join(pconf))), 0)

        executions = None
        if (totmodels > 0):
            Logger.msg("Computing expected outputs... ", 0)

            parser = BeParser()
            parser.DEBUG = config.debug

            with open(models, "r") as modelfile:
                executions = parser.executions_from_string(
                    modelfile.read(), program)

            Logger.log("DONE", 0)

        Logger.msg("Generating program... ", 0)

        outfiles = [config.outprogram]
        if config.jsdir:
            filename = config.outprogram.replace("../",
                                                 "").replace("/", "-").replace(
                                                     "..", "")
            outprogram = "%s/%s" % (config.jsdir, filename)
            outfiles = [outprogram]

        extension = pprinter.get_extension()

        for outfile in outfiles:
            with open(outfile + extension, "w") as f:
                f.write(pprinter.print_program(program, executions))

        Logger.log("DONE", 0)

        if (totmodels > 0):
            Logger.msg("Generating expected outputs... ", 0)

            # Generation of all possible outputs for the JS litmus test #

            execs = pprinter.compute_possible_executions(program, executions)

            if config.debug:
                if execs is not None:
                    with open(config.execs, "w") as exefile:
                        exefile.write("\n".join(execs))

            # Generation of all possible MM interpretations #
            mms = dprinter.print_executions(program, executions)
            for i in range(len(mms)):
                with open(config.dots % (str(i + 1)), "w") as dot:
                    dot.write(mms[i])
                if config.graphviz:
                    with open(config.grap % (str(i + 1)), "w") as dot:
                        graphviz_gen(config, config.dots % (str(i + 1)),
                                     config.grap % (str(i + 1)))

            Logger.log("DONE", 0)

            Logger.log(
                " -> Found %s possible output%s" %
                (len(execs), "" if len(execs) == 1 else "s"), 0)

    return 0
Exemple #27
0
def main(args):
    parser = argparse.ArgumentParser(
        description='EMME: ECMAScript Memory Model Evaluator',
        formatter_class=RawTextHelpFormatter)

    parser.add_argument('input_file',
                        metavar='program',
                        type=str,
                        help='the input file describing the program')

    jsprinters = [
        " - \"%s\": %s" % (x.get_name(), x.get_desc())
        for x in PrintersFactory.get_printers_by_type(PrinterType.PROGRAMS)
    ]
    config = Config()

    # Files generation

    parser.set_defaults(jsprinter=config.jsprinter)
    parser.add_argument(
        '-p',
        '--jsprinter',
        metavar='jsprinter',
        type=str,
        nargs='?',
        help='select the JS printer between (Default is \"%s\"):\n%s' %
        (config.jsprinter, "\n".join(jsprinters)))

    parser.set_defaults(jsdir=None)
    parser.add_argument(
        '-d',
        '--jsdir',
        metavar='jsdir',
        type=str,
        nargs='?',
        help=
        'directory where to store all JS programs. (Default is the same as the input file)'
    )

    parser.set_defaults(graphviz=False)
    parser.add_argument(
        '-g',
        '--graphviz',
        dest='graphviz',
        action='store_true',
        help=
        "generates the png files of each execution (requires neato). (Default is \"%s\")"
        % False)

    parser.set_defaults(relations=config.printing_relations)
    parser.add_argument(
        '-r',
        '--relations',
        metavar='relations',
        type=str,
        nargs='?',
        help=
        'a (comma separated) list of relations to consider in the graphviz file.\nKeyword \"%s\" means all.'
        % ALL)

    parser.set_defaults(prefix=None)
    parser.add_argument(
        '-x',
        '--prefix',
        metavar='prefix',
        type=str,
        nargs='?',
        help=
        'directory where to store the results. (Default is the same as the input file)'
    )

    # Possible analyses

    parser.set_defaults(synth=False)
    parser.add_argument(
        '--synth',
        dest='synth',
        action='store_true',
        help="enables equivalent programs synthesis. (Default is \"%s\")" %
        False)

    parser.set_defaults(unmatched=False)
    parser.add_argument(
        '--unmatched',
        dest='unmatched',
        action='store_true',
        help="enables unmatched outputs analysis. (Default is \"%s\")" % False)

    parser.set_defaults(jsengine=None)
    parser.add_argument(
        '--jsengine',
        metavar='jsengine',
        type=str,
        nargs='?',
        help=
        'the command used to call the JavaScript engine, to use with \"--unmatched\".'
    )

    parser.set_defaults(runs=10)
    parser.add_argument(
        '-n',
        '--runs',
        metavar='runs',
        type=str,
        help=
        'number of runs for the unmatched outputs analysis, to use with \"--unmatched\".\n(Default is \"10\")'
    )

    # Solvers selection

    parser.set_defaults(use_cvc4=False)
    parser.add_argument(
        '-c',
        '--use-cvc4',
        dest='use_cvc4',
        action='store_true',
        help="relies on CVC4 instead of Alloy Analyzer. (Default is \"%s\")" %
        False)

    parser.set_defaults(best=False)
    parser.add_argument(
        '-b',
        '--best',
        dest='best',
        action='store_true',
        help=
        "relies on CVC4 or Alloy Analyzer for best performance. (Default is \"%s\")"
        % False)

    # Simple configurations

    parser.set_defaults(verbosity=1)
    parser.add_argument('-v',
                        dest='verbosity',
                        metavar="verbosity",
                        type=int,
                        help="verbosity level. (Default is \"%s\")" % 1)

    parser.set_defaults(nexecs=-1)
    parser.add_argument(
        '-e',
        '--max-executions',
        dest='nexecs',
        metavar='nexecs',
        type=int,
        help='maximum number of executions. (Default is \"unlimited\")')

    parser.set_defaults(force_solving=False)
    parser.add_argument(
        '-f',
        '--force-solving',
        dest='force_solving',
        action='store_true',
        help=
        "forces the solving part by discharging the previous models. (Default is \"%s\")"
        % False)

    parser.set_defaults(skip_solving=False)
    parser.add_argument('-k',
                        '--skip-solving',
                        dest='skip_solving',
                        action='store_true',
                        help="skips the solving part. (Default is \"%s\")" %
                        False)

    parser.set_defaults(silent=False)
    parser.add_argument('-l',
                        '--silent',
                        dest='silent',
                        action='store_true',
                        help="silent mode. (Default is \"%s\")" % False)

    parser.set_defaults(check_sat=False)
    parser.add_argument(
        '-s',
        '--only-sat',
        dest='check_sat',
        action='store_true',
        help="performs only the satisfiability checking. (Default is \"%s\")" %
        False)

    parser.set_defaults(only_model=False)
    parser.add_argument(
        '-m',
        '--only-model',
        dest='only_model',
        action='store_true',
        help="exits right after the model generation. (Default is \"%s\")" %
        False)

    # Advanced configurations

    parser.set_defaults(threads=1)
    parser.add_argument(
        '-j',
        '--threads',
        metavar='number',
        type=int,
        help='number of threads - EXPERIMENTAL. (Default is \"1\")')

    parser.set_defaults(debug=False)
    parser.add_argument('--debug',
                        dest='debug',
                        action='store_true',
                        help="enables debugging setup. (Default is \"%s\")" %
                        False)

    parser.set_defaults(time=False)
    parser.add_argument(
        '-t',
        '--time',
        dest='time',
        action='store_true',
        help="enables time debugging setup. (Default is \"%s\")" % False)

    parser.set_defaults(no_expand_bounded_sets=False)
    parser.add_argument(
        '--no-exbounded',
        dest='no_expand_bounded_sets',
        action='store_true',
        help=
        "disables the bounded sets quantifier expansion. (Default is \"%s\")" %
        False)

    parser.set_defaults(defines=None)
    parser.add_argument(
        '--defines',
        metavar='defines',
        type=str,
        nargs='?',
        help='the set of preprocessor\'s defines. (Default is none)')

    parser.set_defaults(preproc=CPP)
    parser.add_argument(
        '--preproc',
        metavar='preproc',
        type=str,
        nargs='?',
        help='the memory model preprocessor. (Default is \"%s\")' % CPP)

    if len(sys.argv) == 1:
        parser.print_help()
        sys.exit(1)

    args = parser.parse_args(args)

    prefix = args.prefix

    if not prefix:
        prefix = args.input_file.split("/")
        prefix[-1] = prefix[-1].split(".")[0]
        prefix = "/".join(prefix)
        prefix += "/"

    if not os.path.exists(args.input_file):
        print("File not found: \"%s\"" % args.input_file)
        return 1

    config.inputfile = args.input_file
    config.prefix = prefix
    config.preproc = args.preproc
    config.expand_bounded_sets = not args.no_expand_bounded_sets
    config.verbosity = args.verbosity
    config.defines = args.defines
    config.sat = args.check_sat
    config.only_model = args.only_model
    config.skip_solving = args.skip_solving
    config.printing_relations = args.relations
    config.graphviz = args.graphviz
    config.jsdir = args.jsdir
    config.debug = args.debug
    config.force_solving = args.force_solving
    config.threads = args.threads
    config.jsengine = args.jsengine
    config.runs = args.runs
    config.nexecs = args.nexecs
    config.use_alloy = not args.use_cvc4
    config.unmatched = args.unmatched
    config.time = args.time

    if args.jsprinter in [
            str(x.get_name())
            for x in PrintersFactory.get_printers_by_type(PrinterType.PROGRAMS)
    ]:
        config.jsprinter = args.jsprinter
    else:
        Logger.error("Printer \"%s\" not found" % (args.jsprinter))

    if config.unmatched and not config.jsengine:
        Logger.error("JavaScript engine not specified")
        return 1

    if not config.use_alloy:
        try:
            import CVC4
        except Exception:
            Logger.error("Error importing CVC4 module")
            return 1

    if args.synth and args.best:
        config.hybrid = True

    if not args.synth and not args.unmatched and args.best:
        config.use_alloy = True

    if args.silent:
        config.verbosity = 0

    if args.relations == ALL:
        config.printing_relations = None

    Logger.verbosity = config.verbosity

    Logger.log("** Processing file \"%s\" **" % (config.inputfile), -1)

    try:
        Logger.time = config.time
        ret = -1
        ret = analyze_program(config)

        if ret == 0 and args.synth:
            ret = synth_program(config)
        if ret == 0 and args.unmatched:
            ret = unmatched_analysis(config)

        #cleanup
        if not config.debug:
            del_file(config.block_type)
            del_file(config.bound_int)
            del_file(config.alloy_model)
            del_file(config.cvc_model)
            del_file(config.cvc_model_ex)
            del_file(config.id_type)
            del_file(config.instance)

        Logger.log("\nExiting...", 0)
        return ret
    except Exception as e:
        if config.debug: raise
        print("\nERROR! Run with --debug option for more information")
        return 1