Пример #1
0
def ppz_parallel_encode(phi: CNF,
                        x: Assignment,
                        sig: Permutation,
                        fill_first: bool = False) -> List[bool]:
    # enumerate all versions of phi with free coordinates of x filled in
    phi = phi.simplify()
    logger.info(f"ENCODING {x} with CNF {phi}")
    logger.info(f"{phi.clauses}")

    free_coords = [i + 1 for i, val in enumerate(x) if val == None]
    num_free = len(free_coords)
    phis = [deepcopy(phi) for _ in range(2**num_free)]
    _completions = completions(x)
    if fill_first:
        phis = [
            phi.assign_on_variables(c, free_coords).simplify()
            for phi, c in zip(phis, _completions)
        ]
    enc = []
    for _var in sig:
        var = _var + 1
        logger.info(f"{var}")
        unit_clauses = get_literals_in_unit_clauses_from_lists_of_formulas(
            phis)
        logger.info(f"unit_clauses: {unit_clauses}")

        if var in unit_clauses:
            logger.info(f"variable {var} is in a unit clauses, assigning True")
            for i in range(len(phis)):
                phis[i].assign_single_variable(
                    var, True, in_place=True).simplify_inplace()
        elif -var in unit_clauses:
            logger.info(
                f"variable {var} is in a unit clauses, assigning False")
            for i in range(len(phis)):
                phis[i].assign_single_variable(
                    var, False, in_place=True).simplify_inplace()
        else:
            logger.info(
                f"variable does not appear in unit clause, assigning..")
            for i in range(len(phis)):
                logger.info(f"formula {phis[i]}")
                logger.info(f"assigning {var}: {_completions[i][var-1]}")
                if not fill_first or var not in free_coords:
                    phis[i].assign_single_variable(
                        var, _completions[i][var - 1],
                        in_place=True).simplify_inplace()
                    logger.info(f"updated formula: {phis[i]}")
            if var not in free_coords:
                logger.info(f"variable not free so appending to enc")
                enc.append(x[var - 1])
                logger.info(f"enc: {enc}")
    return enc  # type: ignore
Пример #2
0
def encode_3(phi: CNF, x: Assignment, pi: Permutation):
    enc = []
    x = [x[i] for i in pi]
    phi = phi.rename_perm(pi)
    n = phi.n_vars
    for i in range(n):
        pass
Пример #3
0
def mod_then_parity(n: int, k: int, mod: int) -> CNF:
    phi = []
    for i in range(n//k):
        if i == 0:
            phi.extend(mod_formula(k, mod).clauses)
        else:
            d = {a: a + i*k for a in range(1, k+1)}
            phi.extend(mod_formula(k, 2).rename(d).clauses)
    return CNF(phi)
Пример #4
0
def mod_formula(n: int, mod: int) -> CNF:
    not_satisfying = [x for x in bitstrings(n) if (sum(x) % mod) == 0]
    phi = []
    for x in not_satisfying:
        clause = []
        for _i, v in enumerate(x):
            i = _i +1 
            clause.append(-i if v == 1 else i)
            phi.append(clause)
    return CNF(phi)
Пример #5
0
def get_ith_cnf(index, n, k, m):
    fname = f"cnfs_list_n{n}_k{k}_m{m}.txt"
    if os.path.isfile(fname):
        string = read_index(fname, index)
        clauses = ast.literal_eval(string)
        return CNF(clauses)
    else:
        for i, phi in enumerate(all_cnfs(n, k, m)):
            if i == index:
                return phi
Пример #6
0
def mspas_with_same_free_bits():
    # NOTE: This counterexample was kind of hard to find
    phi = CNF([[-1, 2, -3], [1, -2, 4], [-1, -3, 5], [2, -4, -5]])
    mspas = get_prime_implicants(phi, 2)
    print(phi)
    print("MSPAS")
    pprint(mspas)
    free_coords = [get_free_coords(x) for x in mspas]
    relevant = [x for (x, i) in zip(mspas, free_coords) if i == (0, 4)]
    print()
    print("MSPAs with the same free bits:")
    print(relevant)
    print("Encodings:")
    for x in relevant:
        print(ppz_parallel_encode(phi, x, range(5)))

    draw_assignments_with_mspas(all_solutions(phi), relevant, phi, fname='mspas_with_same_free_bits.svg')
Пример #7
0
def counterexample_same_encoding_inconsistent():
    n = 5
    # phi = CNF([[-1, 4], [5], [-4, -2], [-1, 5]])
    phi = CNF([[5, 2], [-5, 3, 4], [-2, 5, 1], [2, 1]])
    mspas = get_prime_implicants(phi, 2)
    # mspa1 = [False, None, None, False, True] # Inconsistent b/c diverge in the 4th bit
    # mspa2 = [None, False, None, True, True]
    mspa1 = [True, True, None, None, False]
    mspa2 = [True, None, True, None, True]
    print(ppz_parallel_encode(phi, mspa1, list(range(n))))
    print(ppz_parallel_encode(phi, mspa2, list(range(n))))
    # extra = "\n MSPA1: 0**01, MSPA2: *0*11 both have encoding 0 but are inconsitent with one another"
    extra = "\n MSPA1: 11**0, MSPA2: 1*1*1 both have encoding 11 but are inconsistent with one another"

    draw_assignments(
        all_solutions(phi), phi, extra, fname="same_encoding_inconsistent.svg"
    )
Пример #8
0
def ppz_parallel_decode(
    phi: CNF,
    original_encoding,
    num_free_bits,
    sig: Permutation,
    fill_first: bool = False,
) -> Assignment:
    phi = phi.simplify()
    results = []
    # consider all possible locations of free coordinates
    n = phi.n_vars
    all_possible_free_coords = itertools.combinations(range(1, n + 1),
                                                      num_free_bits)

    for free_coords in all_possible_free_coords:
        decoding = ppz_decode_guessed_free_bit_locations(
            phi, original_encoding, free_coords, sig, fill_first)
        if decoding:
            results.append(decoding)

    return results
Пример #9
0
def ppz_once(phi: CNF) -> Optional[TotalAssignment]:
    n = phi.n_vars
    assignment: PartialAssignment = [None for _ in range(n)]
    for var in range(1, n + 1):
        if assignment[var - 1] is not None:  # Already been assigned
            continue

        val = None

        for clause in phi.clauses:
            if len(clause) == 1 and lit_to_var(clause[0]) == var:  # Forced
                val = clause[0] < 1
                break

        if val is None:  # Not forced
            val = random.choice([True, False])

        assignment[var - 1] = val
        phi = phi.assign_single_variable(var, val).simplify()
        if [] in phi.clauses:
            return None

    return assignment  # type: ignore
Пример #10
0
def satisfying_completions(phi: CNF,
                           x: PartialAssignment) -> List[TotalAssignment]:
    return [c for c in completions(x) if phi.evaluate_on_assignment(c)]
Пример #11
0
def sensitivity(phi: CNF, x: TotalAssignment) -> int:
    n = phi.n_vars
    assert len(x) == n
    val = phi.evaluate_on_assignment(x)
    return sum(val != phi.evaluate_on_assignment(flip_assignment_at(x, i))
               for i in range(1, n + 1))
Пример #12
0
def sensitive_at(phi: CNF, x: TotalAssignment, var: int):
    val = phi.evaluate_on_assignment(x)
    return val != phi.evaluate_on_assignment(flip_assignment_at(x, var))
Пример #13
0
def dist_monotone(n: int, k: int, m: int) -> CNF:
    clauses = [sample_monotone_clause(n, k) for _ in range(m)]
    return CNF(clauses)
Пример #14
0
def block_mod_formula(n: int, k: int, mod: int) -> CNF:
    phi = []
    for i in range(n//k):
        d = {a: a + i*k for a in range(1, k+1)}
        phi.extend(mod_formula(k, mod).rename(d).clauses)
    return CNF(phi)