Esempio n. 1
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")
Esempio n. 2
0
    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
Esempio n. 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_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()
Esempio n. 4
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()
Esempio n. 5
0
 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()
Esempio n. 6
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 ...")
  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