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("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(): # 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 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 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 ...") 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 ...") manager_vtree.save_as_dot("output/after-rotate-vtree.dot".encode()) alpha.save_as_dot("output/after-rotate-sdd.dot".encode())
def main(argv=None): options, args = getopt(argv) fnf = None weights = None if options.cnf_filename is not None: print("reading cnf...") fnf = Fnf.from_cnf_file(bytes(options.cnf_filename)) weights = read_weights(options.cnf_filename) elif options.dnf_filename is not None: print("reading dnf...") fnf = Fnf.from_dnf_file(bytes(options.dnf_filename)) weights = read_weights(options.cnf_filename) if options.vtree_filename is not None: print("reading initial vtree...") vtree = Vtree.from_file(bytes(options.vtree_filename)) else: if fnf is None: raise argparse.ArgumentTypeError("CNF or DNF file required") print(f"creating initial vtree {options.initial_vtree_type.decode()}") vtree = Vtree(var_count=fnf.var_count, vtree_type=options.initial_vtree_type) print("creating manager...") manager = SddManager.from_vtree(vtree) manager.set_options(options) if options.sdd_filename is None: print("compiling...") c1 = time.time() node = manager.fnf_to_sdd(fnf) c2 = time.time() secs = c2 - c1 print("") print(f"compilation time : {secs:.3f} sec") else: print("reading sdd from file...") c1 = time.time() node = manager.read_sdd_file(options.sdd_filename) c2 = time.time() secs = c2 - c1 print(f"read time : {secs:.3f} sec") weights = read_weights(options.sdd_filename) wmc = create_wmc(node, weights, args) print_node(node, wmc) if options.verbose: manager.print_stdout() if options.minimize_cardinality: print("\nminimizing cardinality...", end="") c1 = time.time() node = manager.global_minimize_cardinality(node) c2 = time.time() min_card = manager.minimum_cardinality(node) print("") wmc = create_wmc(node, weights, args) print_node(node, wmc) print(f" min cardinality : {min_card} {c2-c1:.3f} sec") manager_vtree = manager.vtree() if options.post_search: node.ref() print("dynamic vtree (post compilation)") print(f" sdd initial size : {node.size()}") c1 = time.time() manager.minimize_limited() c2 = time.time() print(f" dynamic vtree time : {c2-c1:.3f} sec") wmc = create_wmc(node, weights, args) print_node(node, wmc) node.deref() if options.verbose: manager.print_stdout() if options.output_sdd_filename is not None: print("saving compiled sdd ...", end="") node.save(options.output_sdd_filename) print("done") if options.output_sdd_dot_filename is not None: print("saving compiled sdd (dot) ...", end="") node.save_as_dot(options.output_sdd_dot_filename) print("done") if options.output_vtree_filename is not None: print("saving vtree ...", end="") manager_vtree.save(options.output_vtree_filename) print("done") if options.output_vtree_dot_filename is not None: print("saving vtree (dot) ...", end="") manager_vtree.save_as_dot(options.output_vtree_dot_filename) print("done") print("done")