def ex1_b2_r2(): domain = Domain.make(["a", "b"], ["x", "y"], [(0, 1), (0, 1)]) a, b, x, y = domain.get_symbols(domain.variables) support = (a | b) & (~a | ~b) & (x >= 0.0) & (x <= y) & (y <= 1.0) weight = Ite(a, Real(0.6), Real(0.4)) * Ite(b, Real(0.8), Real(0.2))\ * (Ite(x >= Real(0.5), Real(0.5) * x + Real(0.1) * y, Real(0.1) * x + Real(0.7) * y)) return Density(domain, support, weight, [x <= y / 2])
def triangle(nvars, rand_gen): # alpha = rand_gen.uniform(0.05, 0.25) alpha = rand_gen.uniform(0.2, 0.25) remain = nvars % 3 n_tris = int(nvars / 3) variables = [Symbol(f"x{i}", REAL) for i in range(1, nvars + 1)] lbounds = [LE(Real(0), x) for x in variables] ubounds = [LE(x, Real(1)) for x in variables] clauses = [] potentials = [] for i in range(n_tris): x, y, z = variables[3 * i], variables[3 * i + 1], variables[3 * i + 2] xc = None if 3 * i + 3 >= nvars else variables[3 * i + 3] # x_i clauses.append(Or(LE(x, Real(alpha)), LE(Real(1 - alpha), x))) # x_i -- y_i clauses.append( Or(LE(y, Plus(x, Real(-alpha))), LE(Plus(x, Real(alpha)), y))) # x_i -- z_i clauses.append(Or(LE(Real(1 - alpha), x), LE(Real(1 - alpha), z))) clauses.append(Or(LE(x, Real(alpha)), LE(z, Real(alpha)))) # z_i -- y_i clauses.append(LE(z, y)) # x_i -- x_i+1 if xc: clauses.append(Or(LE(x, Real(alpha)), LE(Real(1 - alpha), xc))) clauses.append(Or(LE(Real(1 - alpha), x), LE(xc, Real(alpha)))) pot_yz = Ite(LE(z, y), Times([z, y, Real(100)]), Real(1)) pot_xy = Ite(LE(y, Plus(x, Real(-alpha))), Times(Real(100), Plus(x, y)), Real(1)) potentials.append(pot_xy) potentials.append(pot_yz) if remain == 1: x = variables[3 * n_tris] clauses.append(Or(LE(x, Real(alpha)), LE(Real(1 - alpha), x))) if remain == 2: x, y = variables[3 * n_tris], variables[nvars - 1] # x_n clauses.append(Or(LE(x, Real(alpha)), LE(Real(1 - alpha), x))) # x -- y clauses.append( Or(LE(y, Plus(x, Real(-alpha))), LE(Plus(x, Real(alpha)), y))) potentials.append( Ite(LE(y, Plus(x, Real(-alpha))), Times(Real(100), Plus(x, y)), Real(1))) domain = Domain.make( [], # no booleans [x.symbol_name() for x in variables], [(0, 1) for _ in range(len(variables))]) support = And(lbounds + ubounds + clauses) weight = Times(potentials) if len(potentials) > 1 else potentials[0] return Density(domain, support, weight, []), alpha
def sym_exec_rsicv_add(rs1, rs2, rd, regs): rs1_val = Ite(Equals(rs1, BitVecVal(0, 5)), BitVecVal(0, 32), Select(regs, rs1)) rs2_val = Ite(Equals(rs2, BitVecVal(0, 5)), BitVecVal(0, 32), Select(regs, rs2)) res = BVAdd(rs1_val, rs2_val) regs_n = Store(regs, rd, res) return Ite(Equals(rd, BitVecVal(0, 5)), regs, regs_n)
def test_ite(self): x = Symbol("x") p, q = Symbol("p", INT), Symbol("q", INT) f = Ite(x, p, q) self.assertEqual(f.to_smtlib(daggify=False), "(ite x p q)") self.assertEqual(f.to_smtlib(daggify=True), "(let ((.def_0 (ite x p q))) .def_0)")
def ex_jonathan(): domain = Domain.make(["f0", "d0"], ["r0"], [(10, 45)]) f0, d0 = domain.get_bool_symbols() r0, = domain.get_real_symbols() support = ((f0 & (((d0 | ~d0) & ~(r0 <= 35)) | ((r0 <= 35) & (~d0)))) | (~f0 & (d0 & (r0 <= 35)))) & domain.get_bounds() weight_function = Ite(f0, Real(0.0001), Real(0.00001)) * \ Ite(d0, (r0/10)-1, 8-(r0/10)) * \ Ite(r0 <= 35, -0.001*(r0-27)*(r0-27)+0.3, -0.001*(r0-27)*(r0-27)+0.3) return Density(domain, support, weight_function, queries=[d0])
def test_volume(): domain = Domain.make(["a", "b"], ["x", "y"], [(0, 1), (0, 1)]) a, b, x, y = domain.get_symbols(domain.variables) support = (a | b) & (~a | ~b) & (x >= 0.0) & (x <= y) & (y <= 1.0) weight = Ite(a, Real(0.6), Real(0.4)) * Ite(b, Real(0.8), Real(0.2))\ * (Ite(x >= Real(0.5), Real(0.5) * x + Real(0.1) * y, Real(0.1) * x + Real(0.7) * y)) engine = AdaptiveRejection(domain, support, weight, SAMPLE_COUNT) computed_volume = engine.compute_volume() correction_volume_rej = RejectionEngine(domain, support, weight, SAMPLE_COUNT).compute_volume() assert computed_volume == pytest.approx(correction_volume_rej, rel=APPROX_ERROR)
def test_misc(self): bool_list = [ And(self.x, self.y), Or(self.x, self.y), Not(self.x), self.x, Equals(self.p, self.q), GE(self.p, self.q), LE(self.p, self.q), GT(self.p, self.q), LT(self.p, self.q), Bool(True), Ite(self.x, self.y, self.x) ] # TODO: FORALL EXISTS real_list = [ self.r, Real(4), Plus(self.r, self.s), Plus(self.r, Real(2)), Minus(self.s, self.r), Times(self.r, Real(1)), Div(self.r, Real(1)), Ite(self.x, self.r, self.s), ] int_list = [ self.p, Int(4), Plus(self.p, self.q), Plus(self.p, Int(2)), Minus(self.p, self.q), Times(self.p, Int(1)), Ite(self.x, self.p, self.q), ] for f in bool_list: t = self.tc.walk(f) self.assertEqual(t, BOOL, f) for f in real_list: t = self.tc.walk(f) self.assertEqual(t, REAL, f) for f in int_list: t = self.tc.walk(f) self.assertEqual(t, INT, f)
def sanity_b1_r0(): domain = Domain.make(["a"]) a, = domain.get_symbols() support = TRUE() weight = Ite(a, Real(0.3), Real(0.7)) queries = [a, ~a] return Density(domain, support, weight, queries)
def generate_weights_ijcai17(self, pos_only=True): subformulas = [] for a in self.bools: pos = self._random_polynomial() neg = Real(1) if pos_only else self._random_polynomial() subformulas.append(Ite(a, pos, neg)) return Times(subformulas)
def generate_cond_problem(self, n_real_cond, n_bool_cond): lra_conditions = [ self._random_inequality() for _ in range(n_real_cond) ] bool_conditions = [ self._random_boolean_formula(1) for _ in range(n_bool_cond) ] conditions = lra_conditions + bool_conditions n_cond = n_real_cond + n_bool_cond n_leaves = n_cond + 1 shuffle(conditions) polynomials = [self._random_polynomial() for _ in range(n_leaves)] w_nodes = conditions + polynomials #subdomains = [self.generate_support_cond() for _ in range(n_leaves)] #chi_nodes = conditions + subdomains support = And([ Implies(cond, self.generate_support_cond()) for cond in conditions ]) i = n_cond - 1 while i >= 0: w_nodes[i] = Ite(w_nodes[i], w_nodes[2 * i + 1], w_nodes[2 * i + 2]) #chi_nodes[i] = Ite(chi_nodes[i], chi_nodes[2*i+1], chi_nodes[2*i+2]) i -= 1 #return w_nodes[0], chi_nodes[0] return w_nodes[0], support
def Mux(in0, in1, sel, out): # if Modules.functional # INVAR: out' = Ite(sel = 0, in0, in1) # else # INVAR: ((sel = 0) -> (out = in0)) & ((sel = 1) -> (out = in1)) vars_ = [in0, in1, sel, out] comment = "Mux (in0, in1, sel, out) = (%s, %s, %s, %s)" % (tuple( [x.symbol_name() for x in vars_])) Logger.log(comment, 3) if sel.symbol_type() == BOOL: sel0 = Not(sel) sel1 = sel else: sel0 = EqualsOrIff(sel, BV(0, 1)) sel1 = EqualsOrIff(sel, BV(1, 1)) if Modules.functional: invar = And(EqualsOrIff(out, Ite(sel0, in0, in1))) else: invar = And(Implies(sel0, EqualsOrIff(in0, out)), Implies(sel1, EqualsOrIff(in1, out))) ts = TS(comment) ts.vars, ts.invar = set(vars_), invar return ts
def mem_access(addr, locations, width_idx, idx=0): first_loc = min(2**width_idx, len(locations)) - 1 ite_chain = locations[first_loc] for i in reversed(range(0, first_loc)): location = BV(i, width_idx) ite_chain = Ite(EqualsOrIff(addr, location), locations[i], ite_chain) return ite_chain
def sum_m(tau): return Plus([Int(0)] + [ Plus( Ite(Equals(delta_chi_eq_i[e][i], Int(1)), Int(LAMBDA(i)[0]), Int(0)), Plus([ Ite( Equals(delta_chi_eq_i[len(logical_edges) + r][i], Int(1)), Ite(Equals(delta_e_in_r[e][r], Int(1)), Int(LAMBDA(i)[0]), Int(0)), Int(0)) for r in range(len(logical_edges)) ])) for i in range(JUMPTABLE_MAX) for e in range(len(logical_edges)) if logical_edges[e].source() in tc.get_in_neighbors(tau) ])
def IteExtend(b, t0,t1): orig_width_t0 = t0.get_type().width orig_width_t1 = t1.get_type().width orig_width = max(orig_width_t0,orig_width_t1) t0e = BVZExt(t0, max(orig_width-orig_width_t0, 0)) t1e = BVZExt(t1, max(orig_width-orig_width_t1, 0)) return Ite(b, t0e, t1e)
def test_z3_conversion_ite(self): with Solver(name='z3') as solver: x = Symbol('x') y = Symbol('y') f = Ite(x, y, FALSE()) solver.add_assertion(f) self.assertTrue(solver.solve())
def Bop(bvop, bop, in0, in1, out): # INVAR: (in0 <op> in1) = out vars_ = [in0, in1, out] comment = (bvop.__name__ + " (in0, in1, out) = (%s, %s, %s)") % (tuple( [x.symbol_name() for x in vars_])) Logger.log(comment, 3) in0B = in0.symbol_type() == BOOL in1B = in1.symbol_type() == BOOL outB = out.symbol_type() == BOOL bools = (1 if in0B else 0) + (1 if in1B else 0) + (1 if outB else 0) if bop == None: if in0B: in0 = Ite(in0, BV(1, 1), BV(0, 1)) if in1B: in1 = Ite(in1, BV(1, 1), BV(0, 1)) if outB: out = Ite(out, BV(1, 1), BV(0, 1)) invar = EqualsOrIff(bvop(in0, in1), out) else: if bools == 3: invar = EqualsOrIff(bop(in0, in1), out) elif bools == 0: invar = EqualsOrIff(bvop(in0, in1), out) elif bools == 1: if in0B: invar = EqualsOrIff(bvop(B2BV(in0), in1), out) if in1B: invar = EqualsOrIff(bvop(in0, B2BV(in1)), out) if outB: invar = EqualsOrIff(BV2B(bvop(in0, in1)), out) else: if not in0B: invar = EqualsOrIff(bop(BV2B(in0), in1), out) if not in1B: invar = EqualsOrIff(bop(in0, BV2B(in1)), out) if not outB: invar = EqualsOrIff(B2BV(bop(in0, in1)), out) ts = TS(comment) ts.vars, ts.invar = set(vars_), invar return ts
def test_ite(self): x = Symbol("x") p, q = Symbol("p", INT), Symbol("q", INT) f = Ite(x, p, q) f_string = self.print_to_string(f) self.assertEqual(f_string, "(ite x p q)")
def min_K(tau): return Min([Int(K_MAX)] + [ Min( Ite(Equals(delta_chi_eq_i[e][i], Int(1)), Int(LAMBDA(i)[1]), Int(K_MAX)), Min([ Ite( Equals(delta_chi_eq_i[len(logical_edges) + r][i], Int(1)), Ite(Equals(delta_e_in_r[e][r], Int(1)), Int(LAMBDA(i)[1]), Int(K_MAX)), Int(K_MAX)) for r in range(len(logical_edges)) ])) for i in range(JUMPTABLE_MAX) for r in range(len(logical_edges)) for e in range(len(logical_edges)) if logical_edges[e].source() in tc.get_in_neighbors(tau) ])
def solveDecisionProblem(filename): global robots_info global task_info global task_utilities global k robots_info = {} task_info = {} task_utilities = {} k=0 file = open(filename, "r") mode = 0 for line in file: if line=='\n': mode+=1 elif mode==0: k = int(line.strip()) elif mode==1: task_line = line.split() task_info[task_line[0]] = [int(resource) for resource in task_line[2:]] task_utilities[task_line[0]] = int(task_line[1]) elif mode == 2: robot_line = line.split() robots_info[robot_line[0]] = [int(resource) for resource in robot_line[1:]] file.close() # Each robot may be assigned to at most one task # runs in time |Robots||Tasks||Tasks| oneTask = And([Symbol(robot+taskAssigned).Implies(Not(Symbol(robot+task))) for robot in robots_info.keys() for taskAssigned in task_info.keys() for task in task_info.keys() if (taskAssigned != task)]) # A task is satisfied if and only if all of its resource requirements are met # runs in time |Robots||Tasks||ResourceTypes| tasksSatisfied = And([Iff(Symbol(task +"Sat"), And([GE(Plus([Times(Ite(Symbol(robot+task),Int(1), Int(0)), Int(robots_info[robot][i])) for robot in robots_info.keys()]), Int(task_info[task][i])) for i in range(len(task_info[task]))])) for task in task_info.keys()]) # Is the decision problem satisfied # runs in time |Tasks| decisionProb = GE(Plus([Times(Ite(Symbol(task+"Sat"), Int(1), Int(0)), Int(task_utilities[task])) for task in task_info.keys()]), Int(k)) prob = And(oneTask, tasksSatisfied, decisionProb) model = get_model(prob) return model
def to_weight_function(self): if self.is_leaf(): return Real(self.weight) else: if self.split_variable.symbol_type() == BOOL: condition = self.split_variable else: condition = LE(self.split_variable, Real(self.split_value)) return Ite(condition, self.pos.to_weight_function(), self.neg.to_weight_function())
def test_partial_0b_2r_branch_weight(): domain = Domain.make([], ["x", "y"], real_bounds=(0, 1)) x, y = domain.get_symbols(domain.variables) support = (x >= 0.1) & (x <= 0.9) & (y >= 0.3) & (y <= 0.7) weight = Ite(x <= y, x, y * 3.17) engine = FactorizedXsddEngine(domain, support, weight) computed_volume = engine.compute_volume() should_be = PyXaddEngine(domain, support, weight).compute_volume() # print(computed_volume, should_be) assert computed_volume == pytest.approx(should_be, rel=ERROR)
def hist_to_piecewise_constant(var, breaks, ys): assert (len(breaks) == len(ys)), "dimensions mismatch" assert(all(breaks[i-1] < breaks[i] for i in range(1,len(breaks)))),\ "bin bounds should be sorted" else_branch = Real(0) for i in range(1, len(breaks)): assert (breaks[i - 1] < breaks[i]) interval = And(LE(Real(breaks[i - 1]), var), LE(var, Real(breaks[i]))) else_branch = Ite(interval, Real(ys[i], else_branch)) return else_branch
def test_volume(): # Support: (a | b) & (~a | ~b) & (x >= 0) & (x <= y) & (y <= 10) # Weight: { # a b (x>=0.5): 0.6*0.8*(0.5x+0.1y) 0.5 <= x <= y, x <= y <= 10 # a b !(x>=0.5): 0.6*0.8*(0.1x+0.7y) 0 <= x <= [y, 0.5], x <= y <= 10 # a !b (x>=0.5): 0.6*0.2*(0.5x+0.1y) 0.5 <= x <= y, x <= y <= 10 # a !b !(x>=0.5): 0.6*0.2*(0.1x+0.7y) 0 <= x <= [y, 0.5], x <= y <= 10 # !a b (x>=0.5): 0.4*0.8*(0.5x+0.1y) 0.5 <= x <= y, x <= y <= 10 # !a b !(x>=0.5): 0.4*0.8*(0.1x+0.7y) 0 <= x <= [y, 0.5], x <= y <= 10 # !a !b (x>=0.5): 0.4*0.2*(0.5x+0.1y) 0.5 <= x <= y, x <= y <= 10 # !a !b !(x>=0.5): 0.4*0.2*(0.1x+0.7y) 0 <= x <= [y, 0.5], x <= y <= 10 # } # TODO What if we don't expand the Weight Function, only compile the support? # TODO => Can we reuse the SDD? It doesn't seem so... => Need multiple SDDs to use caching domain = Domain.make(["a", "b"], ["x", "y"], [(0, 1), (0, 1)]) a, b, x, y = domain.get_symbols(domain.variables) support = (a | b) & (~a | ~b) & (x >= 0.0) & (x <= y) & (y <= 1.0) weight = (Ite(a, Real(0.6), Real(0.4)) * Ite(b, Real(0.8), Real(0.2)) * (Ite( x >= Real(0.5), Real(0.5) * x + Real(0.1) * y, Real(0.1) * x + Real(0.7) * y, ))) computed_volume = XsddEngine( domain=domain, support=support, weight=weight, convex_backend=EngineConvexIntegrationBackend(PyXaddEngine()), ).compute_volume() correction_volume_rej = RejectionEngine(domain, support, weight, 1000000).compute_volume() correction_volume_xadd = PyXaddEngine(domain, support, weight).compute_volume() # print(correction_volume_rej, correction_volume_xadd, computed_volume) assert computed_volume == pytest.approx(correction_volume_rej, rel=ERROR) assert computed_volume == pytest.approx(correction_volume_xadd, rel=ERROR)
def ISE(model1, model2, seed, sample_count, engine='pa'): assert(set(model1.get_vars()) == set(model2.get_vars())),\ "M1 vars: {}\n M2 vars: {}".format(model1.get_vars(),model2.get_vars()) support1, weightfun1 = model1.support, model1.weightfun support2, weightfun2 = model2.support, model2.weightfun support_d = Or(support1, support2) weight_d = Ite(And(support1, support2), Times(Minus(weightfun1, weightfun2), Minus(weightfun1, weightfun2)), Ite(support1, Times(weightfun1, weightfun1), Times(weightfun2, weightfun2))) domain, _ = merged_domain(model1, model2) if engine == 'pa': engine = PredicateAbstractionEngine(domain, support_d, weight_d) result = solver.compute_volume() elif engine == 'rej': result = None solver = RejectionEngine(domain, support_d, weight_d, sample_count=sample_count, seed=seed) while result is None: #logger.debug("Attempting with sample_count {}".format( #solver.sample_count)) result = solver.compute_volume() solver.sample_count *= 2 else: raise NotImplementedError() return result
def compile_ftrans(self): if self.ftrans is None: return None ret_trans = TRUE() ret_invar = TRUE() use_ites = False if use_ites: for var, cond_assign_list in self.ftrans.items(): if TS.has_next(var): ite_list = TS.to_prev(var) else: ite_list = var for (condition, value) in reversed(cond_assign_list): if condition == TRUE(): ite_list = value else: ite_list = Ite(condition, value, ite_list) if TS.has_next(ite_list): ret_trans = And(ret_trans, EqualsOrIff(var, ite_list)) else: ret_invar = And(ret_invar, EqualsOrIff(var, ite_list)) else: for var, cond_assign_list in self.ftrans.items(): effects = [] all_neg_cond = [] for (condition, value) in cond_assign_list: effects.append( simplify(Implies(condition, EqualsOrIff(var, value)))) all_neg_cond.append(Not(condition)) if not TS.has_next(var) and not TS.has_next(condition): ret_invar = And(ret_invar, And(effects)) else: ret_trans = And(ret_trans, And(effects)) if TS.has_next(var): no_change = EqualsOrIff(var, TS.to_prev(var)) ret_trans = And( ret_trans, simplify(Implies(And(all_neg_cond), no_change))) return (ret_invar, ret_trans)
def datapoints_to_piecewise_linear(var, xs, ys): assert (len(xs) == len(ys)), "dimensions mismatch" assert(all(xs[i-1] < xs[i] for i in range(1,len(xs)))),\ "x values should be sorted" else_branch = Real(0) for i in range(1, len(xs)): assert (xs[i - 1] < xs[i]) interval = And(LE(Real(float(xs[i - 1])), var), LE(var, Real(float(xs[i])))) a = float((ys[i] - ys[i - 1]) / (xs[i] - xs[i - 1])) b = float(ys[i] - a * xs[i]) poly = Plus(Times(Real(a), var), Real(b)) else_branch = Ite(interval, poly, else_branch) return else_branch
def test_adaptive_weighted_real(): domain = Domain.make([], ["x", "y"], [(-5, 10), (-5, 10)]) x, y = domain.get_symbols(domain.variables) support = (x >= -4) & (x <= y) & (y <= 9) & ((y <= -1) | (y >= 6)) weight = Ite(x <= 2.5, x + y, y * 2) engine = AdaptiveRejection(domain, support, weight, SAMPLE_COUNT, SAMPLE_COUNT / 10) computed_volume = engine.compute_volume() rejection_engine = RejectionEngine(domain, support, weight, SAMPLE_COUNT) correction_volume_rej = rejection_engine.compute_volume() print(computed_volume, correction_volume_rej, APPROX_ERROR * correction_volume_rej) assert computed_volume == pytest.approx(correction_volume_rej, rel=APPROX_ERROR) query = x <= y / 2 prob_adaptive = engine.compute_probability(query) prob_rej = rejection_engine.compute_probability(query) assert prob_adaptive == pytest.approx(prob_rej, rel=APPROX_ERROR)
def printOutput(model, outfile): # format and print output file = open(outfile, "w") if model == None: file.write("0\n") file.close() return total = model.get_py_value(Plus([Times(Ite(Symbol(task+"Sat"), Int(1), Int(0)), Int(task_utilities[task])) for task in task_info.keys()])) file.write(str(total)+"\n\n") for task in task_info.keys(): if (model.get_py_value(Symbol(task+"Sat"))): ret = task + " " + str(task_utilities[task]) for robot in robots_info.keys(): if (model.get_py_value(Symbol(robot+task))): ret+= " " + robot ret+="\n" file.write(ret) else: file.write(task +" 0\n") file.close()
def inspect_manual(engine_or_factory: Union[Engine, Callable], rel_error): if isinstance(engine_or_factory, Engine): engine_factory = lambda d, s, w: engine_or_factory.copy(d, s, w) else: engine_factory = engine_or_factory domain = Domain.make(["a"], ["x"], [(0, 1)]) a, x, = domain.get_symbols() support = ((a & (x <= 0.5)) | (x >= 0.2)) & domain.get_bounds() weight = Ite(a, Real(0.3), Real(0.7)) * x # worlds: a, x <= 0.5, x >= 0.2 integrate 0.3 * x, 0.2 <= x <= 0.5 = 0.0315 # a, x <= 0.5, x <= 0.2 integrate 0.3 * x, 0.0 <= x <= 0.2 = 0.006 # a, x >= 0.5, x <= 0.2 # a, x >= 0.5, x >= 0.2 integrate 0.3 * x, 0.5 <= x <= 1.0 = 0.1125 # ~a, x <= 0.5, x >= 0.2 integrate 0.7 * x, 0.2 <= x <= 0.5 = 0.0735 # ~a, x <= 0.5, x <= 0.2 # ~a, x >= 0.5, x <= 0.2 # ~a, x >= 0.5, x >= 0.2 integrate 0.7 * x, 0.5 <= x <= 1.0 = 0.2625 volume = 0.0315 + 0.006 + 0.1125 + 0.0735 + 0.2625 engine = engine_factory(domain, support, weight) computed_volume = engine.compute_volume() print(computed_volume, volume) assert computed_volume == pytest.approx(volume, rel=rel_error) boolean_query = a boolean_result = 0.0315 + 0.006 + 0.1125 assert engine.compute_probability(boolean_query) == pytest.approx( boolean_result / volume, rel=rel_error) real_query = (x <= 0.3) # worlds: a, x <= 0.5, x >= 0.2, x <= 0.3 integrate 0.3 * x, 0.2 <= x <= 0.3 = 0.0075 # a, x <= 0.5, x <= 0.2, x <= 0.3 integrate 0.3 * x, 0.0 <= x <= 0.2 = 0.006 # a, x >= 0.5, x >= 0.2, x <= 0.3 # ~a, x <= 0.5, x >= 0.2, x <= 0.3 integrate 0.7 * x, 0.2 <= x <= 0.3 = 0.0175 # ~a, x >= 0.5, x >= 0.2, x <= 0.3 real_result = 0.0075 + 0.006 + 0.0175 assert engine.compute_probability(real_query) == pytest.approx( real_result / volume, rel=rel_error)
def generate_weights_cond(self, n_real_cond, n_bool_cond): # TODO: what about overlapping? lra_conditions = [ self._random_inequality() for _ in range(n_real_cond) ] bool_conditions = [ self._random_boolean_formula(1) for _ in range(n_bool_cond) ] conditions = lra_conditions + bool_conditions n_cond = n_real_cond + n_bool_cond n_leaves = n_cond + 1 leaves = [self._random_polynomial() for _ in range(n_leaves)] shuffle(conditions) nodes = conditions + leaves i = n_cond - 1 while i >= 0: nodes[i] = Ite(nodes[i], nodes[2 * i + 1], nodes[2 * i + 2]) i -= 1 return nodes[0]