def generateFromFormulaFile(files, outputFolder, equalNumber, traceLengths, repetitions, numFiles, counter, finiteTraces, misclassificationRate): for fileName in files: with open(fileName) as fileWithFormulas: counter=0 for line in fileWithFormulas: f = Formula.convertTextToFormula(line) print("Generating traces for Formula", str(f)) for minRep in repetitions: for traceLength in traceLengths: num=0 while num<numFiles: generatedTraces = testFileGeneration.generateTracesFromFormula(f, traceLength, minRep, minRep, 100*minRep, finiteTraces=finiteTraces, misclassificationRate=misclassificationRate) patternName = fileName.split("/")[-1] patternName = patternName.split(".")[0] if not os.path.exists(outputFolder+'/'+patternName): os.makedirs(outputFolder+'/'+patternName) testName = outputFolder+patternName+'/'+"{:04}.trace".format(counter) if len(generatedTraces.acceptedTraces) > 0 and len(generatedTraces.rejectedTraces) > 0: generatedTraces.writeTraces(testName) counter += 1 num+=1
def disambiguate(f_1, f_2, wall_locations=[], min_trace_length=None, max_trace_legnth=None, step=None, all_vars_to_consider=[], testing=False): stats_log.debug("disambiguation between {} and {}".format(f_1, f_2)) if min_trace_length is None: min_trace_length = constants.MIN_RANGE_DISAMBIGUATION if max_trace_legnth is None: max_trace_legnth = constants.MAX_RANGE_DISAMBIGUATION if step is None: step = constants.STEP_DISAMBIGUATION for tr_length in range(min_trace_length, max_trace_legnth, step): difference_formula = Formula([ encodingConstants.LOR, Formula([ encodingConstants.LAND, f_1, Formula([encodingConstants.LNOT, f_2]) ]), Formula([ encodingConstants.LAND, Formula([encodingConstants.LNOT, f_1]), f_2 ]) ]) #difference_formula = Formula(["&", f_1, Formula([encodingConstants.LNOT, f_2])]) #difference_formula = Formula(["&", f_2, Formula([encodingConstants.LNOT, f_1])]) # if tr_length > 8: # pdb.set_trace() disambiguation = get_finite_witness(f=difference_formula, trace_length=tr_length, wall_locations=wall_locations, testing=testing) if disambiguation == "unsat": continue elif disambiguation == constants.UNKNOWN_SOLVER_RES: return disambiguation, disambiguation, disambiguation else: (disambiguation_example, init_world, path) = disambiguation logging.debug("+=+=+=++++ disambiguation example is {}".format( disambiguation_example)) if disambiguation_example.evaluateFormulaOnTrace( difference_formula) == False: raise RuntimeError( "looking for witness of satisfiability, but got a trace {} that is not a model for {}" .format(disambiguation_example, difference_formula)) w = World(worldDescriptionJson=init_world, json_type=1) logging.debug( "the distinguishing sequence of actions is {}".format(path)) # emitted_path = w.execute_and_emit_events(path) # logging.debug("+=+=+=++++ emitted path is is {}".format(emitted_path)) logging.debug("distinguishing between {} and {}".format(f_1, f_2)) logging.debug("the initial world is {}".format(w)) logging.debug("the distinguishing traces are {}".format( disambiguation_example)) logging.debug("\n\n====\n\n") return w, path, disambiguation_example logging.error( "Could not find a path disambiguating between {} and {}".format( f_1, f_2)) return None, None, None
def main_compile_json(args): import json from utils import datas from utils.SimpleTree import Formula, DecisionTreeFormula output_file = args.output_file if output_file == "-": output_file = sys.stdout headers = [] expressions = [] for column in args.columns: split = column.split(':', 1) if len(split) == 1: header = expr = split[0] else: header, expr = split headers.append(header.strip()) expressions.append(expr) traces_file_subst = [] for subst in args.traces_file_subst: src, dst = subst.split(':') traces_file_subst.append( (os.path.realpath(src), os.path.realpath(dst))) if isinstance(output_file, str): cm = open(output_file, "w") # else: cm = contextlib.nullcontext(output_file) else: cm = contextlib.contextmanager(lambda: (yield output_file))() with cm as f1: writer = csv.writer(f1) if args.with_header: writer.writerow(headers) #Reading all the json files in the folder input_files = [] for root, dirs, files in os.walk(args.inputs_folder): for file in files: if not file.endswith(args.traces_ext): continue input_files.append(os.path.join(root, file)) constants = dict( SAT="SAT", MaxSAT="MaxSAT", SATDT="SAT-DT", SAT_DT="SAT-DT", MaxSATDT="MaxSAT-DT", MaxSAT_DT="MaxSAT-DT", ) def eval_expr(expr, record, ignore_exceptions=False): try: return eval(expr, dict(record)) except Exception as err: if not ignore_exceptions: msg = f"while evaluating {expr!r} on {input_file}" raise RuntimeError(msg) from err #Collating the results processed = [] for input_file in input_files: try: with open(input_file, 'r') as f2: record = json.load(f2, object_hook=datas.Data) # pre_compute filter for optim purpose if any(not eval_expr(expr, record, ignore_exceptions=True) for expr in args.filters): continue # load additional variables for key in {'traces', 'run', 'result'}: record.setdefault(key, datas.Data()) for key in {'sample', 'formula', 'decisionTree'}: record.setdefault(key, None) if record.traces.filename: record.traces = datas.json_traces_file(record.traces, level=datas.FULL) if record.traces.traces: record.sample = record.traces.traces if record.result.formula: record.formula = Formula.convertTextToFormula( record.result.formula) if record.result.decisionTree: record.decisionTree = DecisionTreeFormula.convertTextToFormula( record.result.decisionTree) for key in { 'result.misclassification', 'algo.args.minScore', 'run.time' }: if not isinstance(record[key], float): continue record[key] = numpy.round(record[key], decimals=15) # filtering traces if any(not eval_expr(expr, record) for expr in args.filters): continue # trace file substitution for src, dst in traces_file_subst: trc = os.path.realpath(record.traces.filename) if os.path.commonpath([trc, src]) != src: continue trc = os.path.join(dst, os.path.relpath(trc, start=src)) if not os.path.isabs(record.traces.filename): trc = os.path.relpath(trc) record.traces = datas.json_traces_file(dict(filename=trc), level=datas.FULL) record.sample = record.traces.traces if record.formula is not None: record.result.misclassification = 1 - record.traces.traces.get_score( record.formula, score='count') record.result.misclassification = numpy.round( record.result.misclassification, decimals=15) break if record.traces.traces: record.sample = record.traces.traces for key in { 'result.misclassification', 'algo.args.minScore', 'run.time' }: if not isinstance(record[key], float): continue record[key] = numpy.round(record[key], decimals=15) values = [eval_expr(expr, record) for expr in expressions] # values = ["" if value is None else value for value in values] # values = [str(value) for value in values] writer.writerow(values) except Exception as err: msg = f"while handling {input_file}" raise RuntimeError(msg) from err processed.append(input_file) print(f"{len(processed)} result files compiled.", file=sys.stderr)
def findSizeOfTextFormula(formulaText): try: formula = Formula.convertTextToFormula(formulaText) return len(formula.getSetOfSubformulas()) except: return "/"
def truthValue(self, formula, timestep): futureTracePositions = self.futurePos(timestep) tableValue = self.truthAssignmentTable[formula][timestep] if tableValue != None: return tableValue # if the table Value is None, but formula is a prop variable elif formula.left is None and formula.right is None: return False else: label = formula.label if label == encodingConstants.LAND: return self.truthValue(formula.left, timestep) and self.truthValue( formula.right, timestep) elif label == encodingConstants.LOR: return self.truthValue(formula.left, timestep) or self.truthValue( formula.right, timestep) elif label == encodingConstants.LNOT: return not self.truthValue(formula.left, timestep) elif label == encodingConstants.IMPLIES: return not self.truthValue(formula.left, timestep) or self.truthValue( formula.right, timestep) elif label == encodingConstants.F: return max([ self.truthValue(formula.left, futureTimestep) for futureTimestep in futureTracePositions ]) # return self.truthValue(formula.left, timestep) or self.truthValue(formula, self.nextPos(timestep)) elif label == encodingConstants.G: return min([ self.truthValue(formula.left, futureTimestep) for futureTimestep in futureTracePositions ]) elif label == encodingConstants.BEFORE: return Trace(self.traceVector[timestep:], literals=self.literals).evaluateFormulaOnTrace( Formula([ encodingConstants.F, Formula([ encodingConstants.LAND, formula.left, Formula([ encodingConstants.F, formula.right ]) ]) ])) # strictly before elif label == encodingConstants.STRICTLY_BEFORE: if timestep == self.lengthOfTrace - 1: return False if self.truthValue(formula.left, timestep) is True: return Trace( self.traceVector[self.nextPos(timestep):], literals=self.literals).evaluateFormulaOnTrace( Formula([encodingConstants.F, formula.right, None])) else: return self.truthValue(formula, self.nextPos(timestep)) # return self.truthValue(formula.left, timestep) and not self.truthValue(formula, self.nextPos(timestep)) elif label == encodingConstants.UNTIL: # logging.debug(timestep, formula) qEventuallyTrue = max([ self.truthValue(formula.right, futureTimestep) for futureTimestep in futureTracePositions ]) == True if qEventuallyTrue == False: return False qTrueNow = self.truthValue(formula.right, timestep) if qTrueNow: return True promiseForTheNextStep = self.truthValue( formula.left, timestep) and self.truthValue( formula, self.nextPos(timestep)) return promiseForTheNextStep elif label == encodingConstants.ENDS: return self.truthValue(formula.left, self.lengthOfTrace - 1) elif label == encodingConstants.X: if timestep == self.lengthOfTrace - 1: return False else: return self.truthValue(formula.left, self.nextPos(timestep))
def get_models( traces, startDepth=1, maxDepth=float("inf"), step=1, optimizeDepth=float("inf"), optimize='count', minScore=0, encoder=DagSATEncoding, maxNumModels=1, timeout=float("inf"), ): if optimizeDepth < maxDepth and optimize is None: logging.warning("Optimize objective not set. Ignoring optimization.") tictoc_z3, time_z3 = TicToc(), 0 tictoc_total = TicToc() tictoc_total.tic() results = [] i = startDepth fg = encoder(i, traces) fg.encodeFormula(optimize=(optimize if i >= optimizeDepth else None)) while len(results) < maxNumModels and i < maxDepth: if fg.set_timeout(timeout - tictoc_total.tocvalue()) <= 0: break tictoc_z3.tic() solverRes = fg.solver.check() time_z3 += tictoc_z3.tocvalue() acceptFormula = False if solverRes == unsat: logging.debug(f"not sat for i = {i}") elif solverRes != sat: logging.debug(f"unknown for i = {i}") break else: acceptFormula = True solverModel = fg.solver.model() formula = fg.reconstructWholeFormula(solverModel) if fg.optimize: score = traces.get_score(formula, fg.optimize) if score < minScore: acceptFormula = False logging.debug( f"score too low for i = {i} ({fg.optimize}={score})") if not acceptFormula: i += step fg = encoder(i, traces) fg.encodeFormula( optimize=(optimize if i >= optimizeDepth else None)) else: if fg.optimize: logging.info( f"found formula {formula.prettyPrint()} ({fg.optimize}={score})" ) else: logging.info(f"found formula {formula.prettyPrint()}") #print(f"found formula {formula}") formula = Formula.normalize(formula) logging.info(f"normalized formula {formula}") if formula not in results: results.append(formula) #prevent current result from being found again block = [] # pdb.set_trace() # print(m) infVariables = fg.getInformativeVariables() logging.debug("informative variables of the model:") for v in infVariables: logging.debug((v, solverModel[v])) logging.debug("===========================") for d in solverModel: # d is a declaration if d.arity() > 0: raise Z3Exception( "uninterpreted functions are not supported") # create a constant from declaration c = d() if is_array(c) or c.sort().kind() == Z3_UNINTERPRETED_SORT: raise Z3Exception( "arrays and uninterpreted sorts are not supported") block.append(c != solverModel[d]) fg.solver.add(Or(block)) # time_total = tictoc_total.tocvalue() # time_z3 # print(time_z3, time_total) return results
def get_rec_dt( traces, misclassification=0, search="breath", timeout=float("inf"), **solver_args, ): return_partial = True format_log = lambda traces: f"recdt on (pos+neg)={len(traces.positive)}+{len(traces.negative)}={len(traces)} traces" log_level = logging.INFO tictoc_total = TicToc() tictoc_total.tic() if search in {"depth", "breath"}: queue = deque() queue_push = lambda nodeTraces, node: queue.append((nodeTraces, node)) if search == "depth": queue_pop = queue.pop elif search == "breath": queue_pop = queue.popleft elif search == "priority": queue = [] queue_push = lambda nodeTraces, node: heapq.heappush( queue, ((-len(traces), random()), nodeTraces, node)) queue_pop = lambda: heapq.heappop(queue)[1:] else: raise NotImplementedError(f"tree search: {search!r}") result = DecisionTreeFormula(label="?") queue_push(traces, result) while queue: nodeTraces, node = queue_pop() if len(nodeTraces) == 0: logging.log(log_level, f"{format_log(nodeTraces)}: Skipping.") childnode.label = "?" continue for leafFormula in [Formula('true'), Formula('false')]: stopping_criterion = nodeTraces.get_misclassification( leafFormula) <= misclassification if stopping_criterion: logging.log( log_level, f"{format_log(nodeTraces)}: Stopping criterion reached.") node.label = leafFormula stopping = True break else: stopping = False if stopping: continue logging.log(log_level, f"{format_log(nodeTraces)}: Solving...") formulas = get_models( traces=nodeTraces, **solver_args, maxNumModels=1, timeout=timeout - tictoc_total.tocvalue(), ) if len(formulas) < 1: # timeout if not return_partial: return None break node.label = formula = formulas[0] accTraces, rejTraces = nodeTraces.splitEval(formula) for subTraces, child in [ (accTraces, "left"), (rejTraces, "right"), ]: childnode = DecisionTreeFormula(label="?") setattr(node, child, childnode) if len(subTraces) == len(nodeTraces): logging.warning( f"{format_log(subTraces)}: {child} child got all the traces, aborting this branch exploration!" ) childnode.label = "..." if not return_partial: msg = f"Ineffective split between {len(nodeTraces)} traces with formula {formula.prettyPrint()}." raise RuntimeError(msg) return None continue logging.debug( f"{format_log(subTraces)}: processing {child} child later...") queue_push(subTraces, childnode) return result
def user_decision_update(): try: t = TicToc() if constants.TESTING: num_disambiguations = 0 disambiguation_stats = [] decision = request.args.get("decision") sessionId = request.args.get("sessionId") candidates = json.loads(request.args.get("candidates")) path = json.loads(request.args.get("path")) context = json.loads(request.args.get("context")) world = World(context, json_type=2) wall_locations = world.get_wall_locations() actions = json.loads(request.args.get("actions")) updated_candidates, updated_formulas = update_candidates( candidates, path, decision, world, actions) answer = {} answer["sessionId"] = sessionId answer["candidates"] = updated_candidates answer["formatted_candidates"] = [ str(f.reFormat()) for f in updated_formulas ] if len(updated_candidates) == 0: answer["status"] = constants.FAILED_CANDIDATES_GENERATION_STATUS return answer elif len(updated_candidates) == 1: answer["status"] = "ok" if constants.TESTING: answer["num_disambiguations"] = num_disambiguations answer["disambiguation_stats"] = disambiguation_stats return answer elif len(updated_candidates) > 1: answer["status"] = "indoubt" converted_candidates = [ Formula.convertTextToFormula(c) for c in updated_candidates ] t = TicToc() t.tic() status, disambiguation_world, disambiguation_path, candidate_1, candidate_2, considered_candidates, disambiguation_trace = create_disambiguation_example( converted_candidates, wall_locations=wall_locations) disambiguation_time = t.tocvalue() if constants.TESTING: num_disambiguations += 1 disambiguation_stats.append(disambiguation_time) if not status == "indoubt": answer["status"] = status if status == "ok": answer["candidates"] = [str(candidate_1)] answer["formatted_candidates"] = [ str(candidate_1.reFormat()) ] else: answer["candidates"] = [] answer["formatted_candidates"] = [] if constants.TESTING: answer["num_disambiguations"] = num_disambiguations answer["disambiguation_stats"] = disambiguation_stats return answer else: answer["world"] = disambiguation_world.export_as_json() formatted_path = convert_path_to_formatted_path( disambiguation_path, disambiguation_world) answer["path"] = formatted_path answer["disambiguation-candidate-1"] = str(candidate_1) answer["disambiguation-candidate-2"] = str(candidate_2) answer["candidates"] = [str(f) for f in considered_candidates] answer["formatted_candidates"] = [ str(f.reFormat()) for f in considered_candidates ] answer["actions"] = disambiguation_path if constants.TESTING: answer["num_disambiguations"] = num_disambiguations answer["disambiguation_stats"] = disambiguation_stats return answer except Exception as e: error_log.error("exception {}".format(e)) return (str(e), 500)