def read_cnf_file(filename: str) -> CNF: with open(filename, "r") as cnfFile: lines = list(filter(lambda line: line.strip(), cnfFile.readlines())) cnf = CNF() cnf.clauses = list(list()) for line in lines: if len(line) > 20 and line[:20] == "c automorphism group": cnf.automorphism_group_size = int(line.split()[-1]) elif line[0] == "c": continue elif line[0] == "p": metadata = line.split() cnf.number_of_literals = int(metadata[2]) cnf.number_of_clauses = int(metadata[3]) else: cnf.clauses.append([int(x) for x in line.split()[:-1]]) return cnf
def produce_cnf( problemType: str, pattern_filename: str, graph_filename: str, target_dir: str = suggested_dir, compute_automorph_size=True, ) -> str: cnf_file_name = "{}/cnf-{}-h-{}-g-{}.cnf".format( target_dir, problemType.strip("--"), pattern_filename.split("/")[-1].split(".")[0], graph_filename.split("/")[-1].split(".")[0], ) # if file already exists, return filename. if path.isfile(cnf_file_name): return cnf_file_name # read input files pattern = read_graph(pattern_filename) graph = read_graph(graph_filename) # create CNF: cnf = CNF(number_of_literals=pattern.number_of_verticies * graph.number_of_verticies, clauses=list(list())) def pair(a: int, v: int) -> int: return (a - 1) * graph.number_of_verticies + v # adding clauses to guarantee that each a is mapped to at least one vertex for a in range(1, pattern.number_of_verticies + 1): cnf.clauses.append( list(pair(a, v) for v in range(1, graph.number_of_verticies + 1))) for a in range(1, pattern.number_of_verticies + 1): for v in range(1, graph.number_of_verticies + 1): for w in range(v + 1, graph.number_of_verticies + 1): cnf.clauses.append([-pair(a, v), -pair(a, w)]) # dictionary, to use for finding non existant pairs: non_existant_pairs = {} for i in range(1, graph.number_of_verticies + 1): non_existant_pairs[i] = list(range(i, graph.number_of_verticies + 1)) for v, w in graph.edges: assert v < w non_existant_pairs[v].remove(w) for a, b in pattern.edges: for v, ws in non_existant_pairs.items(): for w in ws: cnf.clauses.append([-pair(a, v), -pair(b, w)]) if pair(a, v) != pair(a, w) or pair(b, w) != pair(b, v): cnf.clauses.append([-pair(a, w), -pair(b, v)]) # changed second pair to negative, not in the SS notes. if problemType == "--emb": for v in range(1, graph.number_of_verticies + 1): for a in range(1, pattern.number_of_verticies + 1): for b in range(a + 1, pattern.number_of_verticies + 1): clause = [-pair(a, v), -pair(b, v)] if clause not in cnf.clauses: cnf.clauses.append(clause) # count the automorphism group size, by counting embeddings of the pattern unto the pattern. # embed it in a comment comment line on top. auto_size = 0 if compute_automorph_size: auto_size_problem = produce_cnf("--emb", pattern_filename, pattern_filename, target_dir, False) auto_size = int(count_sharp_file(auto_size_problem)[0]) cnf.number_of_clauses = len(cnf.clauses) write_cnf_file(cnf, cnf_file_name, auto_size) return cnf_file_name