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)
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
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
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
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)
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)
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
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)
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
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
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
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)