def test_wmc2(verbose=False): vtree = Vtree(var_count=4, var_order=[2, 1, 4, 3], vtree_type="balanced") sdd = SddManager.from_vtree(vtree) a, b, c, d = [sdd.literal(i) for i in range(1, 5)] # formula = (a & b) | c formula = (a & b) | (b & c) | (c & d) # -d -c -b -a a b c d weights = array('d', [0.8, 0.7, 0.6, 0.5, 0.5, 0.4, 0.3, 0.2]) # Normal WMC wmc = WmcManager(formula, log_mode=False) wmc.set_literal_weights_from_array(weights) wmc_result = wmc.propagate() # Stochastic WMC wmcs = WmcStochastic(formula, log_mode=False) wmcs.set_literal_weights_from_array(weights) nb_pos, nb_neg, scaling = 0, 0, 1 wmcs_results = [] iterations = 1000 for i in range(iterations): random.seed() nb_pos_i, nb_neg_i, scaling_i = wmcs.propagate_counts(bitlength=10) nb_pos += nb_pos_i nb_neg += nb_neg_i scaling = scaling_i wmcs_results.append((nb_pos / (nb_pos + nb_neg)) * scaling) print(wmcs_results[-1]) if verbose: import matplotlib.pyplot as plt plt.plot([i*10 for i in range(iterations)], [wmc_result]*iterations) plt.plot([i*10 for i in range(iterations)], wmcs_results) plt.savefig("stochastic_wmc.png")
def test_wmc1(verbose=False): vtree = Vtree(var_count=4, var_order=[2, 1, 4, 3], vtree_type="balanced") sdd = SddManager.from_vtree(vtree) a, b, c, d = [sdd.literal(i) for i in range(1, 5)] # formula = (a & b) | c formula = (a & b) | (b & c) | (c & d) if verbose: with open("sdd.dot", "w") as out: print(formula.dot(), file=out) # -d -c -b -a a b c d weights = array('d', [0.8, 0.7, 0.6, 0.5, 0.5, 0.4, 0.3, 0.2]) # Normal WMC wmc = WmcManager(formula, log_mode=False) print(f"MC = {wmc.propagate()}") wmc.set_literal_weights_from_array(weights) wmc_result = wmc.propagate() print(f"WMC-Normal = {wmc_result}") # Stochastic WMC wmcs = WmcStochastic(formula, log_mode=False) wmcs.set_literal_weights_from_array(weights) wmcs_result = wmcs.propagate(bitlength=1000) print(f"WMC-Stochastic = {wmcs_result}")
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 var_count = 4 vtree_type = "right".encode() vtree = Vtree(var_count=var_count, vtree_type=vtree_type) manager = SddManager(vtree=vtree) x = [None] + [manager.literal(i) for i in range(1, 5)] # construct the term X_1 ^ X_2 ^ X_3 ^ X_4 alpha = x[1] & x[2] & x[3] & x[4] # construct the term ~X_1 ^ X_2 ^ X_3 ^ X_4 beta = ~x[1] & x[2] & x[3] & x[4] # construct the term ~X_1 ^ ~X_2 ^ X_3 ^ X_4 gamma = ~x[1] & ~x[2] & x[3] & x[4] print("== before referencing:") print(f" live sdd size = {manager.live_size()}") print(f" dead sdd size = {manager.dead_size()}") # ref SDDs so that they are not garbage collected alpha.ref() beta.ref() gamma.ref() print("== after referencing:") print(f" live sdd size = {manager.live_size()}") print(f" dead sdd size = {manager.dead_size()}") # garbage collect manager.garbage_collect() print("== after garbage collection:") print(f" live sdd size = {manager.live_size()}") print(f" dead sdd size = {manager.dead_size()}") alpha.deref() beta.deref() gamma.deref() print("saving vtree & shared sdd ...") if not Path("output").is_dir(): raise Exception(f"Directory 'output' does not exist") vtree.save_as_dot("output/shared-vtree.dot".encode()) manager.shared_save_as_dot("output/shared.dot".encode())
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(): # set up vtree and manager var_count = 4 var_order = [2, 1, 4, 3] vtree_type = "balanced" vtree = Vtree(var_count, var_order, vtree_type) manager = SddManager.from_vtree(vtree) # construct a formula (A^B)v(B^C)v(C^D) print("constructing SDD ... ") a, b, c, d = [manager.literal(i) for i in range(1, 5)] alpha = (a & b) | (b & c) | (c & d) print("done") print("saving sdd and vtree ... ") with open("output/sdd.dot", "w") as out: print(alpha.dot(), file=out) with open("output/vtree.dot", "w") as out: print(vtree.dot(), file=out) print("done")
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")