def make_from_graph(graph): n = graph.vcount() domain = Domain.make([], [f"x{i}" for i in range(n)], real_bounds=(-1, 1)) X = domain.get_symbols() support = smt.And(*((X[e.source] + 1 <= X[e.target]) | (X[e.target] <= X[e.source] - 1) for e in graph.es)) return Density(domain, support & domain.get_bounds(), smt.Real(1))
def run_internal(self): density = Density.from_file(self["filename"]) solver = get_engine(self["solver"], density.domain, density.support, density.weight) if not density.queries or (len(density.queries) == 1 and density.queries[0] == smt.TRUE()): self["volumes"] = [solver.compute_volume()] else: self["volumes"] = [solver.compute_probabilities(density.queries)]
def generate_xor(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] xor = smt.FALSE() for term in terms: xor = (xor | term) & ~(xor & term) return Density(flip_domain(domain), bounds & xor, smt.Real(1.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))
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))
def generate_click_graph(n): def t(c): return smt.Ite(c, one, zero) sim_n, cl_n, b_n, sim_x_n, b_x_n = "sim", "cl", "b", "sim_x", "b_x" domain = Domain.make( # Boolean ["{}_{}".format(sim_n, i) for i in range(n)] + ["{}_{}_{}".format(cl_n, i, j) for i in range(n) for j in (0, 1)] + ["{}_{}_{}".format(b_n, i, j) for i in range(n) for j in (0, 1)], # Real ["{}".format(sim_x_n)] + ["{}_{}_{}".format(b_x_n, i, j) for i in range(n) for j in (0, 1)], real_bounds=(0, 1)) sim = [domain.get_symbol("{}_{}".format(sim_n, i)) for i in range(n)] cl = [[domain.get_symbol("{}_{}_{}".format(cl_n, i, j)) for j in (0, 1)] for i in range(n)] b = [[domain.get_symbol("{}_{}_{}".format(b_n, i, j)) for j in (0, 1)] for i in range(n)] sim_x = domain.get_symbol("{}".format(sim_x_n)) b_x = [[domain.get_symbol("{}_{}_{}".format(b_x_n, i, j)) for j in (0, 1)] for i in range(n)] support = smt.And([ smt.Iff(cl[i][0], b[i][0]) & smt.Iff(cl[i][1], (sim[i] & b[i][0]) | (~sim[i] & b[i][1])) for i in range(n) ]) one = smt.Real(1) zero = smt.Real(0) w_sim_x = t(sim_x >= 0) * t(sim_x <= 1) w_sim = [smt.Ite(s_i, sim_x, 1 - sim_x) for s_i in sim] w_b_x = [ t(b_x[i][j] >= 0) * t(b_x[i][j] <= 1) for i in range(n) for j in (0, 1) ] w_b = [ smt.Ite(b[i][j], b_x[i][j], 1 - b_x[i][j]) for i in range(n) for j in (0, 1) ] weight = smt.Times(*([w_sim_x] + w_sim + w_b_x + w_b)) return Density(domain, support, weight)
def prepare_ratios(): sample_count = 1000 bounds_pool = [(-1, 1), (-10, 10), (-100, 100), (-1000, 1000)] ratios = dict() for name, entry, density_filename in select_benchmark_files( lambda e: "bounds" not in e and benchmark_filter(e)): print("Finding ratios for {}".format(name)) pysmt.environment.push_env() pysmt.environment.get_env().enable_infix_notation = True density = Density.import_from(density_filename) domain = density.domain result_bounds = [] result_ratios = [] for bounds in itertools.product( *[bounds_pool for _ in range(len(domain.real_vars))]): var_bounds = dict(zip(domain.real_vars, bounds)) restricted_domain = Domain(domain.variables, domain.var_types, var_bounds) samples = uniform(restricted_domain, sample_count) labels = evaluate(restricted_domain, density.support, samples) positive_count = sum(labels) if 0 < positive_count < sample_count: ratio = positive_count / sample_count result_bounds.append(var_bounds) result_ratios.append(ratio) ratios[name] = list(zip(result_bounds, result_ratios)) print(name, result_ratios) pysmt.environment.pop_env() with open(get_summary_file(), "rb") as summary_file_reference: summary = pickle.load(summary_file_reference) for name, bounds in ratios.items(): summary[name]["bounds"] = bounds with open(get_summary_file(), "wb") as summary_file_reference: pickle.dump(summary, summary_file_reference)
def accuracy_approx(experiment): key = "accuracy_approx:{}".format(experiment.imported_from_file) if Properties.db.exists(key): return Properties.db.get(key) else: pysmt.environment.push_env() pysmt.environment.get_env().enable_infix_notation = True if os.path.basename(experiment.imported_from_file).startswith("synthetic"): db = Properties.get_db_synthetic(experiment) name = Properties.to_synthetic_name(experiment.imported_from_file) entry = db.get(name) domain = import_domain(json.loads(entry["domain"])) true_formula = nested_to_smt(entry["formula"]) else: density = Density.import_from(experiment.parameters.original_values["domain"]) domain = Domain(density.domain.variables, density.domain.var_types, Properties.get_bound(experiment)) true_formula = density.support learned_formula = nested_to_smt(experiment.results.formula) engine = RejectionEngine(domain, smt.TRUE(), smt.Real(1.0), 100000) accuracy = engine.compute_probability(smt.Iff(true_formula, learned_formula)) pysmt.environment.pop_env() print(accuracy) Properties.db.set(key, accuracy) return accuracy
def from_state(cls, state: dict): density = Density.from_state(state) return cls(density.domain, density.support)
def prepare_smt_lib_benchmark(): benchmark_folder = get_res_root("smt_lib_benchmark") if not os.path.exists(benchmark_folder): os.makedirs(benchmark_folder) zip_file = os.path.join(benchmark_folder, "qf_lra.zip") zip_checksums = [ 'd0031a9e1799f78e72951aa4bacedaff7c0d027905e5de29b5980083b9c51138def165cc18fff205c1cdd0ef60d5d95cf179f0d82ec41ba489acf4383f3e783c' ] # , # '8aa31ada44bbb6705ce58f1f50870da4f3b2d2d27065f3c5c6a17bd484a4cb7eab0c1d55a8d78e48217e66c5b2d876c0708516fb8a383d1ea82a6d4f1278d476'] qf_lra_folder = os.path.join(benchmark_folder, "QF_LRA") if not os.path.exists(qf_lra_folder) and not os.path.exists(zip_file): print("Downloading ZIP file to {}".format(zip_file)) url = "http://smt-lib.loria.fr/zip/QF_LRA.zip" with urllib.request.urlopen(url) as response, open(zip_file, 'wb') as out_file: shutil.copyfileobj(response, out_file) if not os.path.exists(qf_lra_folder): print("Extracting ZIP file {}".format(zip_file)) if checksum(zip_file) not in zip_checksums: fix_zip_file(zip_file) if checksum(zip_file) not in zip_checksums: raise RuntimeError("Corrupted file download") with zipfile.ZipFile(zip_file, 'r') as zip_ref: zip_ref.extractall(benchmark_folder) summary_file = os.path.join(benchmark_folder, "qf_lra_summary.pickle") if not os.path.exists(summary_file): with open(summary_file, "wb") as summary_file_ref: pickle.dump(dict(), summary_file_ref) with open(summary_file, "rb") as summary_file_ref: summary = pickle.load(summary_file_ref) cache_dir = os.path.join(benchmark_folder, "qf_lra_cache") if not os.path.exists(cache_dir): os.makedirs(cache_dir) for filename in glob.glob("{}/**/*.smt*".format(qf_lra_folder), recursive=True): name = filename[filename.find("QF_LRA"):] if name not in summary: summary[name] = dict() cache_filename = "{}{}{}".format(cache_dir, os.path.sep, name) entry = summary[name] if "file_size" not in entry: entry["file_size"] = os.path.getsize(filename) if entry["file_size"] / 1024 > 100: continue density_filename = "{}.density".format(cache_filename) if not os.path.exists(os.path.dirname(density_filename)): os.makedirs(os.path.dirname(density_filename)) domain, formula = None, None pysmt.environment.push_env() pysmt.environment.get_env().enable_infix_notation = True if not os.path.exists(density_filename): print("Importing {}".format(name)) try: domain, formula = import_problem(filename) Density(domain, formula, smt.Real(1.0)).export_to(density_filename) except RuntimeError: print("Error") continue keys = [ "real_variables_count", "bool_variables_count", "operators", "half_spaces" ] if any(k not in entry for k in keys) and (domain is None or formula is None): print("Loading {}".format(name)) density = Density.import_from(density_filename) domain = density.domain formula = density.support if "real_variables_count" not in entry: entry["real_variables_count"] = len(domain.real_vars) if "bool_variables_count" not in entry: entry["bool_variables_count"] = len(domain.bool_vars) if "operators" not in entry: entry["operators"] = OperatorWalker().find_operators(formula) if "half_spaces" not in entry: entry["half_spaces"] = HalfSpaceWalker().find_half_spaces(formula) pysmt.environment.pop_env() with open(summary_file, "wb") as summary_file_ref: pickle.dump(summary, summary_file_ref)
def prepare_synthetic(input_directory, output_directory, runs, sample_size): seeds = [random.randint(0, 2**32 - 1) for _ in range(runs)] db = get_synthetic_db(output_directory, True) os.makedirs(output_directory) for filename in glob.glob("{}/**/synthetics*.txt".format(input_directory), recursive=True): pysmt.environment.push_env() pysmt.environment.get_env().enable_infix_notation = True with open(filename) as file_reference: flat = json.load(file_reference) name = flat["synthetic_problem"]["problem"]["name"] print(name) if not db.exists(name): domain = import_domain( flat["synthetic_problem"]["problem"]["domain"]) formula = nested_to_smt( flat["synthetic_problem"]["problem"]["theory"]) Density(domain, formula, smt.Real(1.0)).export_to( os.path.join(output_directory, "{}.density".format(name))) entry = { "domain": export_domain(domain), "generation": { "h": flat["synthetic_problem"]["half_space_count"], "k": flat["synthetic_problem"]["formula_count"], "l": flat["synthetic_problem"]["terms_per_formula"], "structure": flat["synthetic_problem"]["cnf_or_dnf"], }, "formula": smt_to_nested(formula), "samples": [] } else: entry = dict(db.get(name)) domain = import_domain(entry["domain"]) formula = import_domain(entry["domain"]) samples = entry.get("samples", []) matching_samples = [] for sample in samples: if sample["sample_size"] == sample_size: matching_samples.append(sample) for i in range(runs - len(matching_samples)): seed = seeds[len(matching_samples) + i] samples_file = "{}.{}.{}.samples.npy".format( name, sample_size, seed) labels_file = "{}.{}.{}.labels.npy".format(name, sample_size, seed) np.random.seed(seed) data = uniform(domain, sample_size) np.save(os.path.join(output_directory, samples_file), data) labels = evaluate(domain, formula, data) np.save(os.path.join(output_directory, labels_file), labels) samples.append({ "sample_size": sample_size, "seed": seed, "samples_file": samples_file, "labels_file": labels_file }) entry["samples"] = samples db.set(name, entry) pysmt.environment.pop_env()
def prepare_samples(n, sample_size, reset): samples_dir = get_benchmark_samples_dir() seeds = [random.randint(0, 2**32 - 1) for _ in range(n)] samples_dict = dict() def sample_filter(_entry): if "bounds" in _entry and benchmark_filter(_entry): if "samples" not in _entry["samples"]: return True else: return reset or any( len([ s for s in _entry["samples"] if s["sample_size"] == sample_size and s["bounds"] == _bounds[0] ]) < n for _bounds in _entry["bounds"] if 0.2 <= _bounds[1] <= 0.8) return False for name, entry, filename in select_benchmark_files(sample_filter): print("Creating samples for {}".format(name)) pysmt.environment.push_env() pysmt.environment.get_env().enable_infix_notation = True density = Density.import_from(filename) samples_dict[name] = [] if reset else entry.get("samples", []) for i, (bounds, ratio) in enumerate(entry["bounds"]): if not (0.2 <= ratio <= 0.8): continue print(i, bounds, ratio) previous_samples = [] if reset else ([ s for s in entry.get("samples", []) if s["sample_size"] == sample_size and s["bounds"] == bounds ]) bounded_domain = Domain(density.domain.variables, density.domain.var_types, bounds) for j in range(n - len(previous_samples)): seed = seeds[j] samples_filename = "{}{}{}.{}.{}.{}.sample.npy".format( samples_dir, os.path.sep, name, sample_size, seed, i) labels_filename = "{}{}{}.{}.{}.{}.labels.npy".format( samples_dir, os.path.sep, name, sample_size, seed, i) if not os.path.exists(os.path.dirname(samples_filename)): os.makedirs(os.path.dirname(samples_filename)) random.seed(seed) np.random.seed(seed) samples = uniform(bounded_domain, sample_size) labels = evaluate(bounded_domain, density.support, samples) np.save(samples_filename, samples) np.save(labels_filename, labels) samples_dict[name].append({ "bounds": bounds, "seed": seed, "samples_filename": samples_filename, "labels_filename": labels_filename, "sample_size": sample_size }) pysmt.environment.pop_env() def edit(summary): for _n, _s in samples_dict.items(): summary[_n]["samples"] = _s edit_summary(edit)
def domain_extraction(filename): return Density.import_from(filename).domain
def diabetes_example1(): 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() # support_smaller = ((f0 & ((~(r0 <= 35)) | ~d0)) | # (~f0 & d0 & (r0 <= 35))) & \ # domain.get_bounds() # support_smaller = ((f0 & ((~(r0 <= 35)) | ~d0))) & \ # domain.get_bounds() support_smaller = ((f0 & ~(r0 <= 35) & ~d0) | (f0 & (r0 <= 35) & ~d0)) & domain.get_bounds() weight_function = smt.Ite(f0, smt.Real(0.0001), smt.Real(0.00001)) * \ smt.Ite(d0, (r0/10)-1, 8-(r0/10)) * \ smt.Ite(r0 <= 35, -0.001*(r0-27)*(r0-27)+0.3, -0.001*(r0-27)*(r0-27)+0.3) # # weight_function_smaller = smt.Ite(f0, smt.Real(0.0001), smt.Real(0.00001)) * \ # r0 *\ # smt.Ite(r0 <= 35, -0.001*(r0)*(r0)+0.3, -0.001*(r0)*(r0)+0.3) weight_function_smaller = ( smt.Real(0.00000001) * r0 * r0 * r0 ) # * smt.Real(1000) #<--- add this changes the result from 0.0 to 102 density = Density(domain, support & domain.get_bounds(), weight_function) # weight_function) query = d0 startTime = time.time() rejection_engine = RejectionEngine(density.domain, density.support, density.weight, sample_count=1000000) vol1 = rejection_engine.compute_volume() result1 = rejection_engine.compute_probability(query) endTime = time.time() time1 = endTime - startTime startTime = time.time() xadd_engine = PyXaddEngine(density.domain, density.support, density.weight) vol2 = xadd_engine.compute_volume(add_bounds=False) result2 = xadd_engine.compute_probability(query) endTime = time.time() time2 = endTime - startTime # XsddEngine algebra = PyXaddAlgebra(reduce_strategy=PyXaddAlgebra.FULL_REDUCE) mfxsdd = FXSDD( density.domain, density.support, density.weight, vtree_strategy=balanced, algebra=algebra, ordered=False, ) startTime = time.time() vol3 = mfxsdd.compute_volume(add_bounds=False) result3 = mfxsdd.compute_probability(query=query, add_bounds=False) endTime = time.time() time3 = endTime - startTime print(f"R1 {result1}, time1: {time1}") print(f"R2 {result2}, time2: {time2}") print(f"R3 {result3}, time3: {time3}") print("") print(f"Vol1 {vol1}, time1: {time1}") print(f"Vol2 {vol2}, time2: {time2}") print(f"Vol3 {vol3}, time3: {time3}") return result1, result2, time1, time2