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}")
Exemple #3
0
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()
Exemple #4
0
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")
Exemple #5
0
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())
Exemple #6
0
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")
Exemple #7
0
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()
Exemple #8
0
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())
Exemple #9
0
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")