def short_dnf(): # num variables, clause width, num clauses n, k = 5, 3 m = int(2**(n**0.5)) bound = 2**(n - n / k) num_samples = 1000 num_free_bits = 2 num_fixed = n - num_free_bits assert 2**(num_fixed) * math.comb(n, num_fixed) > bound # obtain k-CNFs # phis = sample(num_samples, dist_R, n, k, m) # print(n) for i, phi in tqdm(all_cnfs(n, k, m)): # find maximally sensitive partial encoding x solns = all_solutions(phi) max_sens = get_prime_implicants(phi, num_free_bits) # draw_assignments(solns, phi) if len(max_sens) > bound + 1: draw_assignments(solns, phi, fname=f"counter_examples/{example_counter}.svg") example_counter += 1 print("=========================") print("CONJECTURE WRONG :O:O:O") print(phi) print(max_sens) num_max_sens = len(max_sens) print( f"{n=}\n {k=}\n {m=}\n {bound=}\n {num_free_bits=}\n {num_max_sens=}" )
def compare_num_free_bits_stats(n, k, num_sample=100): fname = f"samples.csv" samples = sample(num_sample, dist_R, n, k) with open(fname, "a") as f: for phi in tqdm(samples, total=num_sample): m = len(phi.clauses) sols = all_solutions(phi) for j in range(0, n): max_sens = get_prime_implicants(phi, j) num_max_sens = len(max_sens) f.write(", ".join( map(str, [phi.clauses, n, k, m, j, num_max_sens]))) f.write("\n")
def mspas_with_same_free_bits2(): # NOTE: This counterexample was kind of hard to find # phi = CNF([[-1, 2, -3, 4], [1, -2, 4], [-1, -3, 5, -2], [3, 2, -4, -5]]) # 4 sols phi = CNF([[-1, 2, -3, 4], [1, -2, 4, 3], [-1, -3, 5, -2, -4], [3, 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] print(free_coords) 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') draw_assignments(complement(all_solutions(phi)), phi, fname='falsifying.svg')
def is_monotonic(phi): sols = all_solutions(phi) for x in sols: plus_ones = [ flip_assignment_at(x, i + 1) for i in range(len(x)) if x[i] == 0 ] # print() # print() # print(x) # print() for f in plus_ones: # print(f) if f not in sols: return False return True
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" )
def find_collision(n, k, m, j, num_sample=100, fill_first=False): phis = sample_fix_num_clauses(num_sample, dist_R, n, k, m) for phi in phis: phi = phi.simplify_inplace() print(phi.clauses) sols = all_solutions(phi) draw_assignments(sols, phi) mspas = get_prime_implicants(phi, j) enc2assign = defaultdict(list) for mspa in mspas: print(mspa) enc = ppz_parallel_encode(phi, mspa, list(range(n)), fill_first) enc2assign[str(enc)].append(mspa) for k, v in enc2assign.items(): if len(v) > 1: draw_assignments(sols, phi) print("Found a collision!!") print(k, v) if not pairwize_consistent(v): print( "Found a collision between inconsistent assignments!!") print(k, v) exit()
import itertools from src.cnf import impose_blanks from src.random_sat import sample from src.sat_algs import all_solutions # num variables, clause width, num clauses n = 10, k = 3, m = 8 num_free_bits = 3 num_samples = 10 true_blanks = [1, 2, 3] # obtain k-CNFs phis = sample(num_samples, dist_R, n, k, m) for phi in phis: phi_blanks = impose_blanks(phi, true_blanks) # TODO: find maximally sensitive partial encoding x candidates = all_solutions(phi_blanks) # TODO: encode x with parallel_ppz # attempt to decode with all different blanks for blanks in list(itertools.combinations(range(1, n + 1), 3)): psi = impose_blanks(phi, list(blanks)) # TODO: attempt to decode psi
def draw_formula_as_subset(phi, extra_text="", **kwargs): draw_as_subset(all_solutions(phi), phi.n_vars, phi, extra_text, **kwargs)
def draw_solutions(phi: NormalForm, **kwargs): sols = all_solutions(phi) draw_assignments(sols, phi, extra_text='Showing satisfying assignments', **kwargs)
def draw_index(ind, n, k, m): phi = get_ith_cnf(ind, n, k, m) sols = all_solutions(phi) draw_as_subset(sols, n, phi)