Beispiel #1
0
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
Beispiel #2
0
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
Beispiel #3
0
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))
Beispiel #6
0
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
Beispiel #7
0
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
Beispiel #8
0
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)