예제 #1
0
파일: searcher.py 프로젝트: tmeywerk/SHREC
def search_in_node(data, domain, node, h):
    if node.solvable == False:
        return None
    if node.literals is None:
        neg_data_gen = node.to_gen()
        possible_pos_lits = domain.bool_vars.copy()
        possible_neg_lits = domain.bool_vars.copy()
        for i in neg_data_gen:
            assert(not data[i][1])
            possible_pos_lits = [l for l in possible_pos_lits if not data[i][0][l]]
            possible_neg_lits = [l for l in possible_neg_lits if data[i][0][l]]
            if not possible_neg_lits and not possible_pos_lits:
                break
        node.literals = [domain.get_symbol(b) for b in possible_pos_lits] + [~domain.get_symbol(b) for b in possible_neg_lits]
        pos_data = [i for i in range(len(data)) if data[i][1]]
        for l in possible_pos_lits:
            pos_data = [i for i in pos_data if not data[i][0][l]]
        for l in possible_neg_lits:
            pos_data = [i for i in pos_data if data[i][0][l]]
        if pos_data:
            node.next_level_node = build_hierarchy(data, domain, pos_data, False)
        #else it stays None


    if node.next_level_node is None:
        return smt.Or(node.literals)
    q = PriorityQueue()
    q.put(node.next_level_node)
    solutions = []
    neg_idx = list(node.to_gen())
    while not q.empty():
        if len(solutions) + len(q.queue) > h:
            return None
        n = q.get()
        if n.clause is not None:
            solutions += [n.clause]
            continue
        if n.hl_min > 1:
            if n.left is None:
                node.solvable = False
                return None
            q.put(n.left)
            q.put(n.right)
            continue
        with smt.Solver() as solver:
            solution = find_iter(data, domain, list(n.to_gen()) + neg_idx,find_hl, solver)
            if solution is None:
                n.hl_min = 2
                if n.left is None:
                    #print("unsatisfiable node!")
                    return None
                q.put(n.left)
                q.put(n.right)
            else:
                solutions += [solution]
                n.clause = solution
                saturate(data, domain, n)
    return smt.Or(solutions + node.literals)
            
        
예제 #2
0
def generate_strict_cnf(domain, and_count, or_count, half_space_count):
    half_spaces = [generate_half_space_sample(domain, len(domain.real_vars)) for _ in range(half_space_count)]
    candidates = [domain.get_symbol(v) for v in domain.bool_vars] + half_spaces
    candidates += [smt.Not(c) for c in candidates]

    formulas = []
    iteration = 0
    max_iterations = 100 * and_count
    while len(formulas) < and_count:
        if iteration >= max_iterations:
            return generate_strict_cnf(domain, and_count, or_count, half_space_count)
        iteration += 1
        formula_candidates = [c for c in candidates]
        random.shuffle(formula_candidates)
        formula = []
        try:
            while len(formula) < or_count:
                next_term = formula_candidates.pop(0)
                if len(formula) == 0 or smt.is_sat(~smt.Or(*formula) & next_term):
                    formula.append(next_term)
        except IndexError:
            continue
        if len(formulas) == 0 or smt.is_sat(~smt.And(*[smt.Or(*f) for f in formulas]) & smt.Or(*formula)):
            formulas.append(formula)
    return smt.And(*[smt.Or(*f) for f in formulas])
예제 #3
0
    def get_term(self, literal_pool):
        from bitarray import bitarray

        print("Generate term: ", end="")
        for i in range(self.max_tries):
            literals = random.sample(literal_pool, self.l)

            term = smt.Or(*list(zip(*literals))[0])

            covered = bitarray(self.sample_count)
            covered.setall(False)
            significant_literals = 0
            for _, bits in literals:
                prev_size = covered.count()
                covered |= bits
                if (covered.count() - prev_size) / self.sample_count >= 0.05:
                    significant_literals += 1

            if significant_literals == self.l:  # & test_ratio(covered):
                print("y", end="")
                print()
                return term, covered
            else:
                print("x", end="")
        print(" Failed after {} tries".format(self.max_tries))
        raise GeneratorError()
예제 #4
0
    def ast_to_smt(self, node):
        """
        :type node: Node
        """
        def convert_children(number=None):
            if number is not None and len(node.children) != number:
                raise Exception(
                    "The number of children ({}) differed from {}".format(
                        len(node.children), number))
            return [self.ast_to_smt(child) for child in node.children]

        if node.name == "ite":
            return smt.Ite(*convert_children(3))
        elif node.name == "~":
            return smt.Not(*convert_children(1))
        elif node.name == "^":
            return smt.Pow(*convert_children(2))
        elif node.name == "&":
            return smt.And(*convert_children())
        elif node.name == "|":
            return smt.Or(*convert_children())
        elif node.name == "*":
            return smt.Times(*convert_children())
        elif node.name == "+":
            return smt.Plus(*convert_children())
        elif node.name == "-":
            return smt.Minus(*convert_children(2))
        elif node.name == "<=":
            return smt.LE(*convert_children(2))
        elif node.name == ">=":
            return smt.GE(*convert_children(2))
        elif node.name == "<":
            return smt.LT(*convert_children(2))
        elif node.name == ">":
            return smt.GT(*convert_children(2))
        elif node.name == "=":
            return smt.Equals(*convert_children(2))
        elif node.name == "const":
            c_type, c_value = [child.name for child in node.children]
            if c_type == "bool":
                return smt.Bool(bool(c_value))
            elif c_type == "real":
                return smt.Real(float(c_value))
            else:
                raise Exception("Unknown constant type {}".format(c_type))
        elif node.name == "var":
            v_type, v_name = [child.name for child in node.children]
            if v_type == "bool":
                v_smt_type = smt.BOOL
            elif v_type == "real":
                v_smt_type = smt.REAL
            else:
                raise Exception("Unknown variable type {}".format(v_type))
            return smt.Symbol(v_name, v_smt_type)
        else:
            raise RuntimeError("Unrecognized node type '{}'".format(node.name))
예제 #5
0
def dual(n):
    n = 2*n
    domain = Domain.make([], ["x{}".format(i) for i in range(n)], real_bounds=(0, 1))
    x_vars = domain.get_symbols()
    terms = [x_vars[2 * i] <= x_vars[2 * i + 1] for i in range(int(n / 2))]
    disjunction = smt.Or(*terms)
    for i in range(len(terms)):
        for j in range(i + 1, len(terms)):
            disjunction &= ~terms[i] | ~terms[j]
    return FileDensity(domain, disjunction & domain.get_bounds(), smt.Real(1))
예제 #6
0
파일: learner.py 프로젝트: samuelkolb/incal
    def check_example(domain, example_features, dnf_list):
        x_vars = [domain.get_symbol(var) for var in domain.real_vars]
        b_vars = [domain.get_symbol(var) for var in domain.bool_vars]

        formula = smt.Or(
            [smt.And(hyperplane_conjunct) for hyperplane_conjunct in dnf_list])
        substitution = {
            var: example_features[str(var)]
            for var in x_vars + b_vars
        }
        return formula.substitute(substitution).simplify().is_true()
예제 #7
0
def generate_mutual_exclusive(n):
    domain = make_domain(n)

    symbols = domain.get_symbols(domain.real_vars)
    x, symbols = symbols[0], symbols[1:]

    bounds = make_distinct_bounds(domain)

    terms = [x <= v for v in symbols]
    disjunction = smt.Or(*terms)
    for i in range(n):
        for j in range(i + 1, n):
            disjunction &= ~terms[i] | ~terms[j]

    return Density(flip_domain(domain), bounds & disjunction, smt.Real(1.0))
예제 #8
0
def dual_paths(n):
    booleans = []  # ["A{}".format(i) for i in range(n)]
    domain = Domain.make(booleans, ["x{}".format(i) for i in range(n)], real_bounds=(0, 1))
    bool_vars = domain.get_bool_symbols()
    real_vars = domain.get_real_symbols()
    terms = []
    for i in range(n):
        v1, v2 = random.sample(real_vars, 2)
        terms.append(v1 * random.random() <= v2 * random.random())

    paths = []
    for i in range(n):
        paths.append(smt.And(*random.sample(bool_vars + terms, n)))

    return Density(domain, domain.get_bounds() & smt.Or(*paths), smt.Real(1))
예제 #9
0
def mutual_exclusive(n):
    domain = make_domain(n)

    symbols = domain.get_symbols(domain.real_vars)
    x, symbols = symbols[0], symbols[1:]

    bounds = make_distinct_bounds(domain)

    terms = [x <= v for v in symbols]
    disjunction = smt.TRUE()
    for i in range(n):
        for j in range(i + 1, n):
            disjunction &= ~terms[i] | ~terms[j]

    disjunction = smt.simplify(disjunction) & smt.Or(*terms)

    flipped_domain = Domain(list(reversed([v for v in domain.variables if v != "x"])) + ["x"], domain.var_types, domain.var_domains)
    return FileDensity(flipped_domain, disjunction & bounds, smt.Real(1.0))
예제 #10
0
    def get_term(self, literal_pool):
        print("Generate term: ", end="")
        for i in range(self.max_tries):
            literals = random.sample(literal_pool, self.l)

            term = smt.Or(*list(zip(*literals))[0])

            covered = np.zeros(self.sample_count)
            significant_literals = 0
            for _, labels in literals:
                prev_size = sum(covered)
                covered = np.logical_or(covered, labels)
                if (sum(covered) - prev_size) / self.sample_count >= 0.05:
                    significant_literals += 1

            if significant_literals == self.l:  # & test_ratio(covered):
                print("y", end="")
                print()
                return term, covered
            else:
                print("x", end="")
        print(" Failed after {} tries".format(self.max_tries))
        raise GeneratorError()
예제 #11
0
    def compute_volume_from_pieces(
        self, base_support, piecewise_function, labeling_dict
    ):
        # Prepare the support for each piece (not compiled yet)
        term_supports = multimap()
        for piece_weight, piece_support in piecewise_function.pieces.items():
            logger.debug(
                "piece with weight %s and support %s", piece_weight, piece_support
            )
            for term in piece_weight.get_terms():
                term_supports[term].add(piece_support)

        terms_dict = {
            term: smt.Or(*supports) & base_support
            for term, supports in term_supports.items()
        }

        volume = self.algebra.zero()

        for i, (term, support) in enumerate(terms_dict.items()):
            logger.debug("----- Term %s -----", term)

            repl_env, logic_support, literals = extract_and_replace_literals(support)
            literals.labels = labeling_dict

            vtree = self.get_vtree(support, literals)
            support_sdd = self.get_sdd(logic_support, literals, vtree)

            # TODO
            # if logger.getEffectiveLevel() == logging.DEBUG:
            #    filename = f"sdd_{i}.dot"
            #    sdd_to_dot_file(support_sdd, literals, filename, node_to_groups)
            #    logger.debug(f"saved SDD of piece {i} to {filename}")

            subvolume = self.compute_volume_for_piece(term, literals, support_sdd)
            volume = self.algebra.plus(volume, subvolume)
        return volume
예제 #12
0
파일: encoder.py 프로젝트: tmeywerk/SHREC
def find_cnf(data, domain, active_indices, solver, n_c, n_h):
    # Constants
    n_b_original = len(domain.bool_vars)
    n_b = n_b_original * 2
    n_r = len(domain.real_vars)
    n_d = len(data)

    real_features = [[row[v] for v in domain.real_vars] for row, _ in data]
    bool_features = [[row[v] for v in domain.bool_vars] for row, _ in data]
    labels = [row[1] for row in data]

    # Variables
    a_hr = [[
        smt.Symbol("a_hr[{}][{}]".format(h, r), REAL) for r in range(n_r)
    ] for h in range(n_h)]
    b_h = [smt.Symbol("b_h[{}]".format(h), REAL) for h in range(n_h)]
    s_ch = [[smt.Symbol("s_ch[{}][{}]".format(c, h)) for h in range(n_h)]
            for c in range(n_c)]
    s_cb = [[smt.Symbol("s_cb[{}][{}]".format(c, b)) for b in range(n_b)]
            for c in range(n_c)]

    # Aux variables
    s_ih = [[smt.Symbol("s_ih[{}][{}]".format(i, h)) for h in range(n_h)]
            for i in range(n_d)]
    s_ic = [[smt.Symbol("s_ic[{}][{}]".format(i, c)) for c in range(n_c)]
            for i in range(n_d)]

    # Constraints
    for i in active_indices:
        x_r, x_b, label = real_features[i], bool_features[i], labels[i]

        for h in range(n_h):
            sum_coefficients = smt.Plus(
                [a_hr[h][r] * smt.Real(x_r[r]) for r in range(n_r)])
            if label:
                solver.add_assertion(
                    smt.Iff(s_ih[i][h], sum_coefficients + DELTA <= b_h[h]))
            else:
                solver.add_assertion(
                    smt.Iff(s_ih[i][h], sum_coefficients - DELTA <= b_h[h]))

        for c in range(n_c):
            solver.add_assertion(
                smt.Iff(
                    s_ic[i][c],
                    smt.Or([smt.FALSE()] + [(s_ch[c][h] & s_ih[i][h])
                                            for h in range(n_h)] +
                           [s_cb[c][b]
                            for b in range(n_b_original) if x_b[b]] + [
                                s_cb[c][b] for b in range(n_b_original, n_b)
                                if not x_b[b - n_b_original]
                            ])))

        if label:
            solver.add_assertion(smt.And([s_ic[i][c] for c in range(n_c)]))
        else:
            solver.add_assertion(smt.Or([~s_ic[i][c] for c in range(n_c)]))

    if not solver.solve():
        return None
    model = solver.get_model()

    x_vars = [domain.get_symbol(domain.real_vars[r]) for r in range(n_r)]
    half_spaces = [
        smt.Plus([model.get_value(a_hr[h][r]) * x_vars[r]
                  for r in range(n_r)]) <= model.get_value(b_h[h])
        for h in range(n_h)
    ]

    b_vars = [
        domain.get_symbol(domain.bool_vars[b]) for b in range(n_b_original)
    ]
    bool_literals = [b_vars[b] for b in range(n_b_original)]
    bool_literals += [~b_vars[b] for b in range(n_b - n_b_original)]

    conjunctions = [
        [half_spaces[h]
         for h in range(n_h) if model.get_py_value(s_ch[c][h])] + [
             bool_literals[b]
             for b in range(n_b) if model.get_py_value(s_cb[c][b])
         ] for c in range(n_c)
    ]

    return smt.And([smt.Or(conjunction) for conjunction in conjunctions])
예제 #13
0
 def walk_implies(self, left, right):
     return self.walk_smt(smt.Or(smt.Not(left), right))
예제 #14
0
 def walk_or(self, args):
     return smt.Or(*self.walk_smt_multiple(args))
예제 #15
0
def generate_synthetic_data_sampling(data_sets_per_setting, bool_count, real_count, cnf_or_dnf, k, l_per_term, h,
                                     sample_count, max_ratio, seed, prefix="synthetics"):
    def test_ratio(_indices):
        return (1 - max_ratio) * sample_count <= len(_indices) <= max_ratio * sample_count

    data_set_count = 0
    domain = generate_domain(bool_count, real_count)
    while data_set_count < data_sets_per_setting:
        name = get_synthetic_problem_name(prefix, bool_count, real_count, cnf_or_dnf, k, l_per_term, h, sample_count,
                                          seed, max_ratio * 100, data_set_count)
        samples = [get_sample(domain) for _ in range(sample_count)]

        half_spaces = []
        print("Generating half spaces: ", end="")
        if real_count > 0:
            while len(half_spaces) < h:
                half_space = generate_half_space_sample(domain, real_count)
                indices = {i for i in range(sample_count) if smt_test(half_space, samples[i])}
                if True or test_ratio(indices):
                    half_spaces.append((half_space, indices))
                    print("y", end="")
                else:
                    print("x", end="")
        print()

        bool_literals = [(domain.get_symbol(v), {i for i in range(sample_count) if samples[i][v]})
                         for v in domain.bool_vars]

        literal_pool = half_spaces + bool_literals
        literal_pool += [(smt.Not(l), {i for i in range(sample_count)} - indices) for l, indices in literal_pool]
        random.shuffle(literal_pool)

        term_pool = []
        print("Generating terms: ", end="")
        for literals in itertools.combinations(literal_pool, l_per_term):
            term = smt.Or(*[t[0] for t in literals])
            covered = set()
            all_matter = True
            for _, indices in literals:
                prev_size = len(covered)
                covered |= indices
                if (len(covered) - prev_size) / sample_count < 0.05:
                    all_matter = False

            if all_matter:  # & test_ratio(covered):
                term_pool.append((term, covered))
                print("y", end="")
            else:
                print("x", end="")
        print()

        print("Generating formulas: ", end="")
        random.shuffle(term_pool)
        counter = 0
        max_tries = 10000
        for terms in itertools.combinations(term_pool, k):
            if counter >= max_tries:
                print("Restart")
                break
            formula = smt.And(*[t[0] for t in terms])
            covered = {i for i in range(sample_count)}
            all_matter = True
            for _, indices in terms:
                prev_size = len(covered)
                covered &= indices
                if prev_size == len(covered):
                    all_matter = False
            if all_matter & test_ratio(covered):
                print("y({:.2f})".format(len(covered) / sample_count), end="")
                synthetic_problem = SyntheticProblem(problem.Problem(domain, formula, name), "cnf", k, l_per_term, h)
                data_set = synthetic_problem.get_data(sample_count, 1)
                new_sample_positives = [sample for sample in data_set.samples if sample[1]]
                if test_ratio(new_sample_positives):
                    print("c({:.2f})".format(len(new_sample_positives) / sample_count))
                    data_set_count += 1
                    yield data_set
                    break
                else:
                    print("r({:.2f})".format(len(new_sample_positives) / sample_count), end="")
            else:
                print("x", end="")
            print(" ", end="")
            counter += 1
        print()
예제 #16
0
파일: belts.py 프로젝트: cconnett/factorio
def prove_properties(junctions):
    width = max(max(y1 for _, y1, _ in junctions),
                max(y2 for _, _, y2 in junctions)) + 1
    length = max(x for x, _, _ in junctions)
    formula, belts = balancer_flow_formula(junctions, width, length)

    supply = s.Plus(beltway[0].rho for beltway in belts)
    demand = s.Plus(beltway[-1].v for beltway in belts)
    max_theoretical_throughput = s.Min(supply, demand)
    actual_throughput = s.Plus(beltway[-1].flux for beltway in belts)

    fully_balanced_output = []
    max_flux = s.Max(b[-1].flux for b in belts)
    for i, b1 in enumerate(belts):
        fully_balanced_output.append(
            s.Or(s.Equals(b1[-1].flux, max_flux),
                 s.Equals(b1[-1].flux, b1[-1].v)))
    fully_balanced_output = s.And(fully_balanced_output)

    fully_balanced_input = []
    max_flux = s.Max(b[0].flux for b in belts)
    for i, b1 in enumerate(belts):
        fully_balanced_input.append(
            s.Or(s.Equals(b1[0].flux, max_flux),
                 s.Equals(b1[0].flux, b1[0].rho)))
    fully_balanced_input = s.And(fully_balanced_input)

    with s.Solver() as solver:
        solver.add_assertion(s.And(formula))
        solver.push()
        solver.add_assertion(
            s.Not(s.Equals(max_theoretical_throughput, actual_throughput)))

        if not solver.solve():
            print("It's throughput-unlimited!")
        else:
            print("It's throughput-limited; here's an example:")
            m = solver.get_model()
            inputs = tuple(m.get_py_value(beltway[0].rho) for beltway in belts)
            outputs = tuple(m.get_py_value(beltway[-1].v) for beltway in belts)
            print(f'Input lane densities: ({", ".join(map(str, inputs))})')
            print(f'Output lane velocities: ({", ".join(map(str, outputs))})')
            check_balancer_flow(junctions, inputs, outputs)

        solver.pop()
        solver.push()
        solver.add_assertion(s.Not(fully_balanced_input))

        if not solver.solve():
            print("It's input-balanced!")
        else:
            print("It's input-imbalanced; here's an example:")
            m = solver.get_model()
            inputs = tuple(m.get_py_value(beltway[0].rho) for beltway in belts)
            outputs = tuple(m.get_py_value(beltway[-1].v) for beltway in belts)
            print(f'Input lane densities: ({", ".join(map(str, inputs))})')
            print(f'Output lane velocities: ({", ".join(map(str, outputs))})')
            check_balancer_flow(junctions, inputs, outputs)

        solver.pop()
        solver.push()
        solver.add_assertion(s.Not(fully_balanced_output))
        if solver.solve:
            print("It's output-balanced!")
        else:
            print("It's output-imbalanced; here's an example:")
            m = solver.get_model()
            inputs = tuple(m.get_py_value(beltway[0].rho) for beltway in belts)
            outputs = tuple(m.get_py_value(beltway[-1].v) for beltway in belts)
            print(f'Input lane densities: ({", ".join(map(str, inputs))})')
            print(f'Output lane velocities: ({", ".join(map(str, outputs))})')
            check_balancer_flow(junctions, inputs, outputs)
예제 #17
0
def generate_dnf(domain, or_count, and_count, half_space_count):
    formulas = get_formulas(domain, and_count, or_count, half_space_count)
    return smt.Or(smt.And(*formula) for formula in formulas)
예제 #18
0
    def initialize(self, mdp, colors, hole_options, reward_name, okay_states,
                   target_states, threshold, relation):
        logger.warning("This approach has been tested sparsely.")
        prob0E, prob1A = stormpy.compute_prob01min_states(
            mdp, okay_states, target_states)
        sink_states = ~okay_states

        assert len(mdp.initial_states) == 1
        self.state_vars = [
            smt.Symbol("p_{}".format(i), smt.REAL)
            for i in range(mdp.nr_states)
        ]
        self.state_prob1_vars = [
            smt.Symbol("asure_{}".format(i)) for i in range(mdp.nr_states)
        ]
        self.state_probpos_vars = [
            smt.Symbol("x_{}".format(i)) for i in range(mdp.nr_states)
        ]
        self.state_order_vars = [
            smt.Symbol("r_{}".format(i), smt.REAL)
            for i in range(mdp.nr_states)
        ]
        self.option_vars = dict()
        for h, opts in hole_options.items():
            self.option_vars[h] = {
                index: smt.Symbol("h_{}_{}".format(h, opt))
                for index, opt in enumerate(opts)
            }
        self.transition_system = []
        logger.debug("Obtain rewards if necessary")

        rewards = mdp.reward_models[reward_name] if reward_name else None
        if rewards:
            assert not rewards.has_transition_rewards
            state_rewards = rewards.has_state_rewards
            action_rewards = rewards.has_state_action_rewards
            logger.debug(
                "Model has state rewards: {}, has state/action rewards {}".
                format(state_rewards, action_rewards))

            self.transition_system.append(
                self.state_prob1_vars[mdp.initial_states[0]])

        threshold_inequality, action_constraint_inequality = self._to_smt_relation(
            relation)  # TODO or GE
        self.transition_system.append(
            threshold_inequality(self.state_vars[mdp.initial_states[0]],
                                 smt.Real(float(threshold))))

        state_order_domain_constraint = smt.And([
            smt.And(smt.GE(var, smt.Real(0)), smt.LE(var, smt.Real(1)))
            for var in self.state_order_vars
        ])
        self.transition_system.append(state_order_domain_constraint)
        #TODO how to ensure that prob is zero if there is no path.

        select_parameter_value_constraints = []
        for h, opts in self.option_vars.items():
            select_parameter_value_constraints.append(
                smt.Or(ov for ov in opts.values()))
            for i, opt1 in enumerate(opts.values()):
                for opt2 in list(opts.values())[i + 1:]:
                    select_parameter_value_constraints.append(
                        smt.Not(smt.And(opt1, opt2)))
        #logger.debug("Consistency: {}".format(smt.And(select_parameter_value_constraints)))
        self.transition_system.append(
            smt.And(select_parameter_value_constraints))

        for state in mdp.states:
            if sink_states.get(state.id):
                assert rewards is None
                self.transition_system.append(
                    smt.Equals(self.state_vars[state.id], smt.REAL(0)))
                #logger.debug("Constraint: {}".format(self.transition_system[-1]))
                self.transition_system.append(
                    smt.Not(self.state_prob1_vars[state.id]))
                #logger.debug("Constraint: {}".format(self.transition_system[-1]))
                self.transition_system.append(
                    smt.Equals(self.state_order_vars[state.id], smt.Real(0)))
                #logger.debug("Constraint: {}".format(self.transition_system[-1]))
            elif target_states.get(state.id):
                self.transition_system.append(
                    smt.Equals(self.state_order_vars[state.id], smt.Real(1)))
                #logger.debug("Constraint: {}".format(self.transition_system[-1]))
                self.transition_system.append(self.state_prob1_vars[state.id])
                #logger.debug("Constraint: {}".format(self.transition_system[-1]))

                if rewards is None:
                    self.transition_system.append(
                        smt.Equals(self.state_vars[state.id], smt.Real(1)))
                    #logger.debug("Constraint: {}".format(self.transition_system[-1]))
                else:
                    self.transition_system.append(
                        self.state_probpos_vars[state.id])
                    #logger.debug("Constraint: {}".format(self.transition_system[-1]))
                    self.transition_system.append(
                        smt.Equals(self.state_vars[state.id], smt.Real(0)))
                    #logger.debug("Constraint: {}".format(self.transition_system[-1]))
            else:
                state_in_prob1A = False
                state_in_prob0E = False
                if prob0E.get(state.id):
                    state_in_prob0E = True
                else:
                    self.transition_system.append(
                        smt.Equals(self.state_order_vars[state.id],
                                   smt.Real(1)))
                    #logger.debug("Constraint: {}".format(self.transition_system[-1]))
                    self.transition_system.append(
                        self.state_probpos_vars[state.id])
                    #logger.debug("Constraint: {}".format(self.transition_system[-1]))
                if rewards and not state_in_prob0E:
                    if prob1A.get(state.id):
                        self.transition_system.append(
                            self.state_prob1_vars[state.id])
                        logger.debug("Constraint: {}".format(
                            self.transition_system[-1]))
                        state_in_prob1A = True

                for action in state.actions:
                    action_index = mdp.nondeterministic_choice_indices[
                        state.id] + action.id
                    #logger.debug("Action index: {}".format(action_index))
                    precondition = smt.And([
                        self.option_vars[hole][list(option)[0]] for hole,
                        option in colors.get(action_index, dict()).items()
                    ])
                    reward_value = None
                    if rewards:
                        reward_const = (rewards.get_state_reward(
                            state.id) if state_rewards else 0.0) + (
                                rewards.get_state_action_reward(action_index)
                                if action_rewards else 0.0)
                        reward_value = smt.Real(reward_const)
                    act_constraint = action_constraint_inequality(
                        self.state_vars[state.id],
                        smt.Plus([
                            smt.Times(smt.Real(t.value()), self.
                                      state_vars[t.column])
                            for t in action.transitions
                        ] + [reward_value] if reward_value else []))
                    full_act_constraint = act_constraint
                    if state_in_prob0E:
                        if not rewards:
                            full_act_constraint = smt.And(
                                smt.Implies(self.state_probpos_vars[state.id],
                                            act_constraint),
                                smt.Implies(
                                    smt.Not(self.state_probpos_vars),
                                    smt.Equals(self.state_vars[state.id],
                                               smt.Real(0))))
                        self.transition_system.append(
                            smt.Implies(
                                precondition,
                                smt.Iff(
                                    self.state_probpos_vars[state.id],
                                    smt.Or([
                                        smt.And(
                                            self.state_probpos_vars[t.column],
                                            smt.LT(
                                                self.state_order_vars[
                                                    state.id],
                                                self.state_order_vars[
                                                    t.column]))
                                        for t in action.transitions
                                    ]))))
                        #logger.debug("Constraint: {}".format(self.transition_system[-1]))
                    if rewards and not state_in_prob1A:
                        # prob_one(state) <-> probpos AND for all succ prob_one(succ)
                        self.transition_system.append(
                            smt.Implies(
                                precondition,
                                smt.Iff(
                                    self.state_prob1_vars[state.id],
                                    smt.And([
                                        self.state_prob1_vars[t.column]
                                        for t in action.transitions
                                    ] + [self.state_probpos_vars[state.id]]))))
                        #logger.debug("Constraint: {}".format(self.transition_system[-1]))
                    self.transition_system.append(
                        smt.Implies(precondition, full_act_constraint))
                    #logger.debug("Constraint: {}".format(self.transition_system[-1]))

        if rewards:
            self.transition_system.append(
                smt.And([smt.GE(sv, smt.Real(0)) for sv in self.state_vars]))
        else:
            self.transition_system.append(
                smt.And([
                    smt.And(smt.GE(sv, smt.Real(0)), smt.LE(sv, smt.Real(1)))
                    for sv in self.state_vars
                ]))

        #print(self.transition_system)
        formula = smt.And(self.transition_system)
        logger.info("Start SMT solver")
        model = smt.get_model(formula)

        if model:
            logger.info("SAT: Found {}".format(model))
        else:
            logger.info("UNSAT.")
예제 #19
0
    def learn_partial(self, solver, domain: Domain, data: np.ndarray,
                      labels: np.ndarray, new_active_indices: Set):

        # Constants
        n_b_original = len(domain.bool_vars)
        n_b = n_b_original * 2
        n_r = len(domain.real_vars)

        n_h_original = self.half_space_count if n_r > 0 else 0
        n_h = n_h_original * 2 if self.allow_negations else n_h_original

        n_c = self.conjunction_count
        n_d = data.shape[0]

        real_indices = np.array(
            [domain.var_types[v] == smt.REAL for v in domain.variables])
        real_features = data[:, real_indices]
        bool_features = data[:, np.logical_not(real_indices)]

        # Variables
        a_hr = [[
            smt.Symbol("a_hr[{}][{}]".format(h, r), REAL) for r in range(n_r)
        ] for h in range(n_h_original)]
        b_h = [
            smt.Symbol("b_h[{}]".format(h), REAL) for h in range(n_h_original)
        ]
        s_ch = [[smt.Symbol("s_ch[{}][{}]".format(c, h)) for h in range(n_h)]
                for c in range(n_c)]
        s_cb = [[smt.Symbol("s_cb[{}][{}]".format(c, b)) for b in range(n_b)]
                for c in range(n_c)]

        # Aux variables
        s_ih = [[smt.Symbol("s_ih[{}][{}]".format(i, h)) for h in range(n_h)]
                for i in range(n_d)]
        s_ic = [[smt.Symbol("s_ic[{}][{}]".format(i, c)) for c in range(n_c)]
                for i in range(n_d)]

        def pair(real: bool, c: int, index: int) -> Tuple[FNode, FNode]:
            if real:
                return s_ch[c][index], s_ch[c][index + n_h_original]
            else:
                return s_cb[c][index], s_cb[c][index + n_b_original]

        def order_equal(pair1, pair2):
            x_t, x_f, y_t, y_f = pair1 + pair2
            return smt.Iff(x_t, y_t) & smt.Iff(x_f, y_f)

        def order_geq(pair1, pair2):
            x_t, x_f, y_t, y_f = pair1 + pair2
            return x_t | y_f | ((~x_f) & (~y_t))

        def pairs(c: int) -> List[Tuple[FNode, FNode]]:
            return [pair(True, c, i) for i in range(n_h_original)
                    ] + [pair(False, c, i) for i in range(n_b_original)]

        def order_geq_lex(c1: int, c2: int):
            pairs_c1, pairs_c2 = pairs(c1), pairs(c2)
            assert len(pairs_c1) == len(pairs_c2)
            constraints = smt.TRUE()
            for j in range(len(pairs_c1)):
                condition = smt.TRUE()
                for i in range(j):
                    condition &= order_equal(pairs_c1[i], pairs_c2[i])
                constraints &= smt.Implies(condition,
                                           order_geq(pairs_c1[j], pairs_c2[j]))
            return constraints

        # Constraints
        for i in new_active_indices:
            x_r, x_b, label = [float(val) for val in real_features[i]
                               ], bool_features[i], labels[i]

            for h in range(n_h_original):
                sum_coefficients = smt.Plus(
                    [a_hr[h][r] * smt.Real(x_r[r]) for r in range(n_r)])
                solver.add_assertion(
                    smt.Iff(s_ih[i][h], sum_coefficients <= b_h[h]))

            for h in range(n_h_original, n_h):
                solver.add_assertion(
                    smt.Iff(s_ih[i][h], ~s_ih[i][h - n_h_original]))

            for c in range(n_c):
                solver.add_assertion(
                    smt.Iff(
                        s_ic[i][c],
                        smt.
                        Or([smt.FALSE()] + [(s_ch[c][h] & s_ih[i][h])
                                            for h in range(n_h)] +
                           [s_cb[c][b]
                            for b in range(n_b_original) if x_b[b]] + [
                                s_cb[c][b] for b in range(n_b_original, n_b)
                                if not x_b[b - n_b_original]
                            ])))

            # --- [start] symmetry breaking ---
            # Mutually exclusive
            if "m" in self.symmetries:
                for c in range(n_c):
                    for h in range(n_h_original):
                        solver.add_assertion(~(s_ch[c][h]
                                               & s_ch[c][h + n_h_original]))
                    for b in range(n_b_original):
                        solver.add_assertion(~(s_cb[c][b]
                                               & s_cb[c][b + n_b_original]))

            # Normalized
            if "n" in self.symmetries:
                for h in range(n_h_original):
                    solver.add_assertion(
                        smt.Equals(b_h[h], smt.Real(1.0))
                        | smt.Equals(b_h[h], smt.Real(0.0)))

            # Vertical symmetries
            if "v" in self.symmetries:
                for c in range(n_c - 1):
                    solver.add_assertion(order_geq_lex(c, c + 1))

            # Horizontal symmetries
            if "h" in self.symmetries:
                for h in range(n_h_original - 1):
                    solver.add_assertion(a_hr[h][0] >= a_hr[h + 1][0])
            # --- [end] symmetry breaking ---

            if label:
                solver.add_assertion(smt.And([s_ic[i][c] for c in range(n_c)]))
            else:
                solver.add_assertion(smt.Or([~s_ic[i][c] for c in range(n_c)]))

        solver.solve()
        model = solver.get_model()

        x_vars = [domain.get_symbol(domain.real_vars[r]) for r in range(n_r)]
        half_spaces = [
            smt.Plus(
                [model.get_value(a_hr[h][r]) * x_vars[r]
                 for r in range(n_r)]) <= model.get_value(b_h[h])
            for h in range(n_h_original)
        ] + [
            smt.Plus(
                [model.get_value(a_hr[h][r]) * x_vars[r]
                 for r in range(n_r)]) > model.get_value(b_h[h])
            for h in range(n_h - n_h_original)
        ]

        b_vars = [
            domain.get_symbol(domain.bool_vars[b]) for b in range(n_b_original)
        ]
        bool_literals = [b_vars[b] for b in range(n_b_original)]
        bool_literals += [~b_vars[b] for b in range(n_b - n_b_original)]

        conjunctions = [[
            half_spaces[h]
            for h in range(n_h) if model.get_py_value(s_ch[c][h])
        ] + [
            bool_literals[b]
            for b in range(n_b) if model.get_py_value(s_cb[c][b])
        ] for c in range(n_c)]

        return smt.And([smt.Or(conjunction) for conjunction in conjunctions])
예제 #20
0
    def __getExpressionTree(symbolicExpression):
        # TODO LATER: take into account bitwise shift operations
        args = []
        castType = None
        if len(symbolicExpression.args) > 0:
            for symbolicArg in symbolicExpression.args:
                arg, type = Solver.__getExpressionTree(symbolicArg)
                args.append(arg)
                if castType is None:
                    castType = type
                else:
                    if castType.literal == 'Integer':
                        if type.literal == 'Real':
                            castType = type
                    # TODO LATER: consider other possible castings
            if castType.literal == 'Real':
                for i in range(len(args)):
                    args[i] = pysmt.ToReal(args[i])

        if isinstance(symbolicExpression, sympy.Not):
            if castType.literal == 'Integer':
                return pysmt.Equals(args[0], pysmt.Int(0)), Type('Bool')
            elif castType.literal == 'Real':
                return pysmt.Equals(args[0], pysmt.Real(0)), Type('Bool')
            elif castType.literal == 'Bool':
                return pysmt.Not(args[0]), Type('Bool')
            else: # castType.literal == 'BitVector'
                return pysmt.BVNot(args[0]), Type('BitVector')
        elif isinstance(symbolicExpression, sympy.Lt):
            return pysmt.LT(args[0], args[1]), Type('Bool')
        elif isinstance(symbolicExpression, sympy.Gt):
            return pysmt.GT(args[0], args[1]), Type('Bool')
        elif isinstance(symbolicExpression, sympy.Ge):
            return pysmt.GE(args[0], args[1]), Type('Bool')
        elif isinstance(symbolicExpression, sympy.Le):
            return pysmt.LE(args[0], args[1]), Type('Bool')
        elif isinstance(symbolicExpression, sympy.Eq):
            return pysmt.Equals(args[0], args[1]), Type('Bool')
        elif isinstance(symbolicExpression, sympy.Ne):
            return pysmt.NotEquals(args[0], args[1]), Type('Bool')
        elif isinstance(symbolicExpression, sympy.And):
            if castType.literal == 'Bool':
                return pysmt.And(args[0], args[1]), Type('Bool')
            else: # type.literal == 'BitVector'
                return pysmt.BVAnd(args[0], args[1]), castType
        elif isinstance(symbolicExpression, sympy.Or):
            if castType.literal == 'Bool':
                return pysmt.Or(args[0], args[1]), Type('Bool')
            else:  # type.literal == 'BitVector'
                return pysmt.BVOr(args[0], args[1]), castType
        elif isinstance(symbolicExpression, sympy.Xor):
            return pysmt.BVXor(args[0], args[1]), castType
        elif isinstance(symbolicExpression, sympy.Add):
            return pysmt.Plus(args), castType
        elif isinstance(symbolicExpression, sympy.Mul):
            return pysmt.Times(args), castType
        elif isinstance(symbolicExpression, sympy.Pow):
            return pysmt.Pow(args[0], args[1]), castType
        # TODO LATER: deal with missing modulo operator from pysmt
        else:
            if isinstance(symbolicExpression, sympy.Symbol):
                symbolType = Variable.symbolTypes[symbolicExpression.name]
                literal = symbolType.getTypeForSolver()
                designator = symbolType.designatorExpr1
                type = Type(literal, designator)
                return Solver.__encodeTerminal(symbolicExpression, type), type
            elif isinstance(symbolicExpression, sympy.Integer):
                type = Type('Integer')
                return Solver.__encodeTerminal(symbolicExpression, type), type
            elif isinstance(symbolicExpression, sympy.Rational):
                type = Type('Real')
                return Solver.__encodeTerminal(symbolicExpression, type), type
            elif isinstance(symbolicExpression, sympy.Float):
                type = Type('Real')
                return Solver.__encodeTerminal(symbolicExpression, type), type
            else:
                type = Type('Real')
                return Solver.__encodeTerminal(symbolicExpression, type), type
예제 #21
0
 def to_smt(self):
     return sc.Or(self._folA.to_smt(), self._folB.to_smt())
예제 #22
0
 def __or__(self, other: 'SMTBit') -> 'SMTBit':
     return type(self)(smt.Or(self.value, other.value))
예제 #23
0
print(variables)

constraints = []
for var in variables:
    string = var.__repr__()
    # add requirement that all a_i, c_i > -1
    if string[0] == "a" or string[0] == "c":
        constraints.append(SMT.GT(var, SMT.Int(-1)))
    # add requirement that b_i > 0
    else:
        constraints.append(SMT.GT(var, SMT.Int(0)))

for i in range(0, 3 * cap, 3):
    # add requirement that either a_i =0 or c_i = 0
    constraints.append(
        SMT.Or(SMT.Equals(variables[i], SMT.Int(0)),
               SMT.Equals(variables[i + 2], SMT.Int(0))))
    # add requirement that if a_i = 0 and c_i = 0 then b_i = 1
    constraints.append(
        SMT.Or(
            SMT.Or(SMT.GT(variables[i], SMT.Int(0)),
                   SMT.GT(variables[i + 2], SMT.Int(0))),
            SMT.Equals(variables[i + 1], SMT.Int(1))))

solver = SMT.Solver(name="z3")
print("constraints:")
for c in constraints:
    print(c)
    solver.add_assertion(c)

# add equations
예제 #24
0
    def learn_partial(self, solver, domain, data, new_active_indices):
        # Constants
        n_b_original = len(domain.bool_vars)
        n_b = n_b_original * 2
        n_r = len(domain.real_vars)

        n_h_original = self.half_space_count if n_r > 0 else 0
        n_h = n_h_original * 2 if self.allow_negations else n_h_original

        n_c = self.conjunction_count
        n_d = len(data)

        real_features = [[row[v] for v in domain.real_vars] for row, _ in data]
        bool_features = [[row[v] for v in domain.bool_vars] for row, _ in data]
        labels = [row[1] for row in data]

        # Variables
        a_hr = [[
            smt.Symbol("a_hr[{}][{}]".format(h, r), REAL) for r in range(n_r)
        ] for h in range(n_h_original)]
        b_h = [
            smt.Symbol("b_h[{}]".format(h), REAL) for h in range(n_h_original)
        ]
        s_ch = [[smt.Symbol("s_ch[{}][{}]".format(c, h)) for h in range(n_h)]
                for c in range(n_c)]
        s_cb = [[smt.Symbol("s_cb[{}][{}]".format(c, b)) for b in range(n_b)]
                for c in range(n_c)]

        # Aux variables
        s_ih = [[smt.Symbol("s_ih[{}][{}]".format(i, h)) for h in range(n_h)]
                for i in range(n_d)]
        s_ic = [[smt.Symbol("s_ic[{}][{}]".format(i, c)) for c in range(n_c)]
                for i in range(n_d)]

        # Constraints
        for i in new_active_indices:
            x_r, x_b, label = real_features[i], bool_features[i], labels[i]

            for h in range(n_h_original):
                sum_coefficients = smt.Plus(
                    [a_hr[h][r] * smt.Real(x_r[r]) for r in range(n_r)])
                solver.add_assertion(
                    smt.Iff(s_ih[i][h], sum_coefficients <= b_h[h]))

            for h in range(n_h_original, n_h):
                solver.add_assertion(
                    smt.Iff(s_ih[i][h], ~s_ih[i][h - n_h_original]))

            for c in range(n_c):
                solver.add_assertion(
                    smt.Iff(
                        s_ic[i][c],
                        smt.And([smt.TRUE()] + [(~s_ch[c][h] | s_ih[i][h])
                                                for h in range(n_h)] +
                                [
                                    ~s_cb[c][b]
                                    for b in range(n_b_original) if not x_b[b]
                                ] + [
                                    ~s_cb[c][b]
                                    for b in range(n_b_original, n_b)
                                    if x_b[b - n_b_original]
                                ])))

            if label:
                solver.add_assertion(smt.Or([s_ic[i][c] for c in range(n_c)]))
            else:
                solver.add_assertion(smt.And([~s_ic[i][c]
                                              for c in range(n_c)]))

        solver.solve()
        model = solver.get_model()

        x_vars = [domain.get_symbol(domain.real_vars[r]) for r in range(n_r)]
        half_spaces = [
            smt.Plus(
                [model.get_value(a_hr[h][r]) * x_vars[r]
                 for r in range(n_r)]) <= model.get_value(b_h[h])
            for h in range(n_h_original)
        ] + [
            smt.Plus(
                [model.get_value(a_hr[h][r]) * x_vars[r]
                 for r in range(n_r)]) > model.get_value(b_h[h])
            for h in range(n_h - n_h_original)
        ]

        b_vars = [
            domain.get_symbol(domain.bool_vars[b]) for b in range(n_b_original)
        ]
        bool_literals = [b_vars[b] for b in range(n_b_original)]
        bool_literals += [~b_vars[b] for b in range(n_b - n_b_original)]

        conjunctions = [[
            half_spaces[h]
            for h in range(n_h) if model.get_py_value(s_ch[c][h])
        ] + [
            bool_literals[b]
            for b in range(n_b) if model.get_py_value(s_cb[c][b])
        ] for c in range(n_c)]

        return smt.Or([smt.And(conjunction) for conjunction in conjunctions])
예제 #25
0
def smt_to_nested(expression):
    # type: (FNode) -> str
    """
    Converts an smt expression to a nested formula
    :param expression: An SMT expression (FNode)
    :return: A string representation (lisp-style)
        Functional operators can be: &, |, *, +, <=, <, ^
        Variables are represented as (var type name)
        Constants are represented as (const type name)
        Types can be: real, int, bool
    """
    def convert_children(op):
        return "({} {})".format(
            op, " ".join(smt_to_nested(arg) for arg in expression.args()))

    def format_type(smt_type):
        if smt_type == smt.REAL:
            return "real"
        if smt_type == smt.INT:
            return "int"
        if smt_type == smt.BOOL:
            return "bool"
        raise RuntimeError("No type corresponding to {}".format(smt_type))

    if expression.is_and():
        return convert_children("&")
    if expression.is_or():
        return convert_children("|")
    if expression.node_type() == IMPLIES:
        return smt_to_nested(
            smt.Or(smt.Not(expression.args()[0]),
                   expression.args()[1]))
    if expression.is_iff():
        return smt_to_nested(
            smt.And(smt.Implies(expression.args()[0],
                                expression.args()[1]),
                    smt.Implies(expression.args()[1],
                                expression.args()[0])))
    if expression.is_not():
        return convert_children("~")
    if expression.is_times():
        return convert_children("*")
    if expression.is_plus():
        return convert_children("+")
    if expression.is_minus():
        return convert_children("-")
    if expression.is_ite():
        return convert_children("ite")
    if expression.node_type() == POW:
        exponent = expression.args()[1]
        if exponent.is_constant() and exponent.constant_value() == 1:
            return smt_to_nested(expression.args()[0])
        else:
            return convert_children("^")
    if expression.is_le():
        return convert_children("<=")
    if expression.is_lt():
        return convert_children("<")
    if expression.is_equals():
        return convert_children("=")
    if expression.is_symbol():
        return "(var {} {})".format(format_type(expression.symbol_type()),
                                    expression.symbol_name())
    if expression.is_constant():
        value = expression.constant_value()
        if isinstance(value, fractions.Fraction):
            value = float(value)
        return "(const {} {})".format(format_type(expression.constant_type()),
                                      value)

    raise RuntimeError("Cannot convert {} (of type {})".format(
        expression, expression.node_type()))