def main(): # Start from a given CNF and VTREE file vtree = Vtree.from_file(bytes(here / "input" / "simple.vtree")) sdd = SddManager.from_vtree(vtree) print(f"Created an SDD with {sdd.var_count()} variables") root = sdd.read_cnf_file(bytes(here / "input" / "simple.cnf")) # For DNF functions use `read_dnf_file` # If the vtree is not given, you can also use 'from_cnf_file` # Model Counting wmc = root.wmc(log_mode=True) w = wmc.propagate() print(f"Model count: {int(math.exp(w))}") # Weighted Model Counting lits = [None] + [sdd.literal(i) for i in range(1, sdd.var_count() + 1)] # Positive literal weight wmc.set_literal_weight(lits[1], math.log(0.5)) # Negative literal weight wmc.set_literal_weight(-lits[1], math.log(0.5)) w = wmc.propagate() print(f"Weighted model count: {math.exp(w)}") # Visualize SDD and VTREE print("saving sdd and vtree ... ", end="") with open(here / "output" / "sdd.dot", "w") as out: print(sdd.dot(), file=out) with open(here / "output" / "vtree.dot", "w") as out: print(vtree.dot(), file=out) print("done")
def to_pysdd(self, varnums): """ Convert this Vtree into a Vtree from PySDD. If len(varnums) == 0, a vtree with one variable is returned instead """ if len(varnums) == 0: return PysddVtree.new_with_var_order(1, [1], "balanced") # After skimming the documention of the PySDD library, there doesn't # seem to be an easy way to manually 'build' a vtree. # However, there is a save/load mechanism, so we'll use that instead. # Inline documentation of such files: # ids of vtree nodes start at 0 # ids of variables start at 1 # vtree nodes appear bottom-up, children before parents # # file syntax: # vtree number-of-nodes-in-vtree # L id-of-leaf-vtree-node id-of-variable # I id-of-internal-vtree-node id-of-left-child id-of-right-child for internal_id, node in enumerate(self.all_nodes()): node._internal_id = internal_id with tempfile.NamedTemporaryFile(mode="w+") as f: f.write("c Generated by PyWMI\n") f.write(f"vtree {self.count()}\n") self._to_pysdd(f, varnums) f.flush() vtree = PysddVtree.from_file(f.name) return vtree
def main(): # set up vtree and manager vtree = Vtree.from_file("input/opt-swap.vtree".encode()) manager = SddManager.from_vtree(vtree) print("reading sdd from file ...") alpha = manager.read_sdd_file("input/opt-swap.sdd".encode()) print(f" sdd size = {alpha.size()}") # ref, perform the minimization, and then de-ref alpha.ref() print("minimizing sdd size ... ", end="") manager.minimize() # see also manager.minimize_limited() print("done!") print(f" sdd size = {alpha.size()}") alpha.deref() # augment the SDD print("augmenting sdd ...") beta = alpha * (manager.l(4) + manager.l(5)) print(f" sdd size = {beta.size()}") # ref, perform the minimization again on new SDD, and then de-ref beta.ref() print("minimizing sdd ... ", end="") manager.minimize() print("done!") print(f" sdd size = {beta.size()}") beta.deref()
def main(): # set up vtree and manager vtree = Vtree.from_file(bytes(here / "input" / "big-swap.vtree")) manager = SddManager.from_vtree(vtree) print("reading sdd from file ...") alpha = manager.read_sdd_file("input/big-swap.sdd".encode()) print(f" sdd size = {alpha.size()}") # to perform a swap, we need the manager's vtree manager_vtree = manager.vtree() # ref alpha (no dead nodes when swapping) alpha.ref() # using size of sdd normalized for manager_vtree as baseline for limit manager.init_vtree_size_limit(manager_vtree) limit = 2.0 manager.set_vtree_operation_size_limit(limit) print(f"modifying vtree (swap node 7) (limit growth by {limit:.1f}x) ... ", end="") succeeded = manager_vtree.swap(manager, 1) # limited print("succeeded!" if succeeded == 1 else "did not succeed!") print(f" sdd size = {alpha.size()}") print("modifying vtree (swap node 7) (no limit) ... ", end="") succeeded = manager_vtree.swap(manager, 0) # not limited print("succeeded!" if succeeded == 1 else "did not succeed!") print(f" sdd size = {alpha.size()}") print("updating baseline of size limit ...") manager.update_vtree_size_limit() left_vtree = manager_vtree.left() limit = 1.2 manager.set_vtree_operation_size_limit(limit) print(f"modifying vtree (swap node 5) (limit growth by {limit}x) ... ", end="") succeeded = left_vtree.swap(manager, 1) # limited print("succeeded!" if succeeded == 1 else "did not succeed!") print(f" sdd size = {alpha.size()}") limit = 1.3 manager.set_vtree_operation_size_limit(limit) print(f"modifying vtree (swap node 5) (limit growth by {limit}x) ... ", end="") succeeded = left_vtree.swap(manager, 1) # limited print("succeeded!" if succeeded == 1 else "did not succeed!") print(f" sdd size = {alpha.size()}") # deref alpha, since ref's are no longer needed alpha.deref()
def sddConstructorFromFile(self,sddFName): self.sddfName = sddFName if os.path.isfile(self.sddfName+".sdd") and os.path.isfile(self.sddfName+".vtree") and os.path.isfile(self.sddfName+".map") : with open(self.sddfName + ".map", "r") as f: self.nameMappingDic = json.load(f) vtree = Vtree.from_file((self.sddfName+".vtree").encode()) self.sdd = SddManager.from_vtree(vtree) self.formula = self.sdd.read_sdd_file((self.sddfName+".sdd").encode()) else: print("Please provide correct files") sys.exit()
def main(): # set up vtree and manager vtree = Vtree.from_file(bytes(here / "input" / "rotate-left.vtree")) manager = SddManager.from_vtree(vtree) # construct the term X_1 ^ X_2 ^ X_3 ^ X_4 x = [None] + [manager.literal(i) for i in range(1, 5)] alpha = x[1]*x[2]*x[3]*x[4] # to perform a rotate, we need the manager's vtree manager_vtree = manager.vtree() manager_vtree_right = manager_vtree.right() print("saving vtree & sdd ...") if not Path("output").is_dir(): raise Exception(f"Directory 'output' does not exist") manager_vtree.save_as_dot("output/before-rotate-vtree.dot".encode()) alpha.save_as_dot("output/before-rotate-sdd.dot".encode()) # ref alpha (so it is not gc'd) alpha.ref() # garbage collect (no dead nodes when performing vtree operations) print(f"dead sdd nodes = {manager.dead_count()}") print("garbage collection ...") manager.garbage_collect() print(f"dead sdd nodes = {manager.dead_count()}") print("left rotating ... ", end="") succeeded = manager_vtree_right.rotate_left(manager, 0) print("succeeded!" if succeeded == 1 else "did not succeed!") # deref alpha, since ref's are no longer needed alpha.deref() # the root changed after rotation, so get the manager's vtree again # this time using root_location manager_vtree = manager.vtree() print("saving vtree & sdd ...") if not Path("output").is_dir(): raise Exception(f"Directory 'output' does not exist") manager_vtree.save_as_dot("output/after-rotate-vtree.dot".encode()) alpha.save_as_dot("output/after-rotate-sdd.dot".encode())
def do_model_count(self, filename): # create vtree vtree_path = CounterFactory.create("minic2d").create_vtree(filename) vtree = Vtree.from_file(bytes(vtree_path.encode())) sdd = SddManager.from_vtree(vtree) # read CNF root = sdd.read_cnf_file(bytes(filename.encode())) # do model counting wmc = root.wmc(log_mode=False) # add weights weights = get_weights_from_cnf_file(filename) lits = [sdd.literal(i) for i in range(1, sdd.var_count() + 1)] assert len(weights) == 2 * len(lits), \ "Unexpected len {} for weights, got {}. Weights:\n{}".format(len(weights), 2 * len(lits), weights) for i in range(len(lits)): wmc.set_literal_weight(lits[i], weights[2 * i]) wmc.set_literal_weight(-lits[i], weights[2 * i + 1]) # write visualisation of SDD and Vtree to files sdd_file = os.path.abspath( os.path.join(os.path.dirname(filename), "sdd.")) vtree_file = os.path.abspath( os.path.join(os.path.dirname(filename), "vtree-sdd.")) with open(sdd_file + "dot", "w") as out: out.write(sdd.dot()) with open(vtree_file + "dot", "w") as out: out.write(vtree.dot()) # (graph,) = pydot.graph_from_dot_file(sdd_file + "dot") # graph.write_png(sdd_file + "png") # (graph,) = pydot.graph_from_dot_file(vtree_file + "dot") # graph.write_png(vtree_file + "png") return wmc.propagate()
def main(): arg_parser = argparse.ArgumentParser(description="problog pipeline") arg_parser.add_argument("--bif-file", "-b", help="The input bayesian network") arg_parser.add_argument("--pl-file", "-p", help="The input problog file") arg_parser.add_argument("cnf_file", help="The output cnf file") arg_parser.add_argument("--enc", "-e", default=1, help="The enc type 1 or 2", type=int) arg_parser.add_argument( "--cnf-type", "-c", default="c2d", help="The type of cnf file to output (c2d for minic2d or cachet)") arg_parser.add_argument("--verbose", "-v", default=False, help="Verbose output", type=bool, nargs='?', const=True) args = arg_parser.parse_args() if (args.bif_file is None and args.pl_file is None) or \ (args.bif_file is not None and args.pl_file is not None): print("one input file required") return -1 c2d = True if args.cnf_type == "c2d": c2d = True elif args.cnf_type == "cachet": c2d = False else: print("unknwon cnf type") return -1 is_bif = args.bif_file is not None file_name = args.bif_file if is_bif else args.pl_file enc1 = args.enc == 1 verbose = args.verbose contents = None with open(file_name, 'r') as f: contents = f.read() variables = None cnf = None weights = None evidence = None queries = None start_time = time.time() if is_bif: variables, cnf, weights, queries = parse_bif(contents, enc1, verbose) else: variables, cnf, weights, evidence, queries = parse_srl( contents, verbose) cnf_time = time.time() # if verbose: # print("cnf latex:") # print(len(cnf.args)) # clauses = cnf.args # for clause in clauses: # print("$", latex_print(clause), "$") # print() ints = cnf_to_ints(cnf, variables) if evidence is not None: for ev_name, ev_val in evidence: idx = variables.index(ev_name) + 1 if not ev_val: idx = -idx ints.append([idx]) save_cnf(args.cnf_file, ints, variables, weights, c2d) vtree_time = None if c2d: vtree_name = args.cnf_file + ".vtree" print("miniC2D:") minic2d = subprocess.run( [MINIC2D_PATH, '-c', args.cnf_file, '-o', vtree_name]) if minic2d.returncode != 0: print("error creating vtree") return -1 vtree_time = time.time() print("calculating sdd") vtree = Vtree.from_file(vtree_name.encode()) sdd = SddManager.from_vtree(vtree) root = sdd.read_cnf_file(args.cnf_file.encode()) print("sdd node count:", sdd.count()) print("sdd size:", sdd.size()) if verbose: sdd.print_stdout() print() wmc = root.wmc(log_mode=False) w = wmc.propagate() print("model count:", w) nlits = sdd.var_count() assert nlits == len(variables) for idx in range(nlits): i = idx + 1 w_pos = weights[variables[idx]][0] w_neg = weights[variables[idx]][1] wmc.set_literal_weight(sdd.literal(i), w_pos) wmc.set_literal_weight(sdd.literal(-i), w_neg) w = wmc.propagate() print("weighted count:", w) print() print("queries:") if queries is not None: for query in queries: idx = variables.index(query) + 1 pr = wmc.literal_pr(sdd.literal(idx)) print("P(", query, ") =\t", pr) end_time = time.time() print() print("cnf variables:", len(variables), "clauses: ", len(ints)) print() print("total time:\t", end_time - start_time) print("cnf time:\t", cnf_time - start_time) if vtree_time is not None: print("vtree time:\t", vtree_time - cnf_time) print("count time:\t", end_time - vtree_time) return 0