def internal_san_checker(): sys.stderr.write( "Starting internal sanity check with {} classes.\n".format( len(classes))) ProgressBar.create(len(classes)) for clas in classes: if len(clas) < 2: continue print('Sanity checking the class %s' % str(clas)) for l in range(1, check_len + 1): for p in PermSet(l): last = None for i in clas: if last is None: last = p.avoids(MeshPatt.unrank(classpatt, mps[i])) continue av = p.avoids(MeshPatt.unrank(classpatt, mps[i])) if av != last: print('Noooooooooooooooo') print(MeshPatt.unrank(classpatt, mps[i - 1])) print('') print(mps[i]) return last = av ProgressBar.progress() ProgressBar.finish() print("Sanity check completed.")
def coincify(self, maxdepth=3, multbox=True, q_check=True, force_len=None): cnt = len(self.mps) n = self.mps.n sys.stderr.write('Shading lemma coincifier\n') ProgressBar.create(len(self.mps)) for mpi, mp in enumerate(self.mps): ProgressBar.progress() if True: for mpj in range(mpi+1, len(self.mps)): mp2 = self.mps[mpj] if self.uf.find(self.mps[mp]) != self.uf.find(self.mps[mp2]) and tsa5_coincident(mp, mp2, maxdepth, multbox=multbox, q_check=q_check, force_len=force_len): self.uf.unite(self.mps[mp], self.mps[mp2]) else: poss = [] for (i,j) in mp.non_pointless_boxes(): if (i,j) not in mp.mesh: # if all_points_all_dir(mp, (i,j), maxdepth, cut=True): mp2 = mp.shade((i,j)) if self.uf.find(self.mps[mp]) != self.uf.find(self.mps[mp2]) and tsa5_coincident(mp, mp2, maxdepth, multbox=multbox, q_check=q_check, force_len=force_len): self.uf.unite(self.mps[mp], self.mps[mp2]) # for sh in mp.can_shade((i,j)): # if simultaneous and (i,j) not in mp.mesh: # poss.append((sh, set([(i,j)]))) # if not simultaneous: # self.uf.unite(self.mps[mp], self.mps[mp.shade((i,j))]) # # if simultaneous: # for i in range(n+1): # for j in range(n+1): # for di in range(-1,2): # for dj in range(-1,2): # if (di == 0) == (dj == 0): # continue # i2,j2 = (i+di, j+dj) # if 0 <= i2 < n+1 and 0 <= j2 < n+1: # for sh in mp.can_shade2((i,j),(i2,j2)): # poss.append((sh, set([(i,j),(i2,j2)]))) # # def bt(at, nm, used): # if at == len(poss): # mp2 = mp.shade(nm) # self.uf.unite(self.mps[mp], self.mps[mp2]) # return # # bt(at + 1, nm, used) # if poss[at][0] not in used and not (nm & poss[at][1]): # bt(at + 1, nm | poss[at][1], used | set([poss[at][0]])) # # bt(0, set(), set()) ProgressBar.finish()
def __init__(self, n, patt=None): self.n = n self.patt = patt self.mps = [] self.idx = {} sys.stderr.write('Generating mesh patterns\n') ProgressBar.create(2**((n+1)*(n+1)) * (factorial(n) if patt is None else 1)) for i,mp in enumerate(MeshPatterns(n, patt)): ProgressBar.progress() self.mps.append(mp) self.idx[mp] = i ProgressBar.finish()
def __init__(self, n, patt=None): self.n = n self.patt = patt self.mps = [] self.idx = {} sys.stderr.write('Generating mesh patterns\n') ProgressBar.create(2**((n + 1) * (n + 1)) * (factorial(n) if patt is None else 1)) for i, mp in enumerate(gen_meshpatts(n, patt)): ProgressBar.progress() self.mps.append(mp) self.idx[mp] = i assert MeshPatt.unrank(patt, i) == mp ProgressBar.finish()
def filter_binary(patterns, cpatt): binarypatterns = set(patterns) for l in range(len(cpatt), len(cpatt) * 2 + 1): sys.stderr.write("Permutations of length {}\n".format(l)) ProgressBar.create(factorial(l)) for perm in perm_set.of_length(l): ProgressBar.progress() poss = [] for res in cpatt.occurrences_in(perm): con = set(perm[i] for i in res) colcnt = 0 col = [-1]*len(perm) for v in perm: if v in con: colcnt += 1 else: col[v] = colcnt rowcnt = 0 row = [-1]*len(perm) for v in range(len(perm)): if v in con: rowcnt += 1 else: row[v] = rowcnt # bad is the set of boxes that contain points and can not be shaded bad = set( (u,v) for u,v in zip(col,row) if u != -1 ) # cur is the set of boxes that can be shaded cur = set( (u,v) for u in range(len(cpatt)+1) for v in range(len(cpatt)+1) if (u,v) not in bad ) poss.append(shad_to_binary(cur, len(cpatt) + 1)) occurring = set() nonbinary = set() for binpatt in binarypatterns: for occ in poss: if is_subset(binpatt, occ): if binpatt in occurring: nonbinary.add(binpatt) # print(MeshPatt.unrank(cpatt, binpatt)) # print(perm) break else: occurring.add(binpatt) binarypatterns -= nonbinary ProgressBar.finish() return binarypatterns
def take_closure(self): it = 0 while True: it += 1 changed = False sys.stderr.write('Shading lemma closure (no %d)\n' % (it)) cnt = len(self.mps) ss = {} for i in range(cnt): ss.setdefault(self.uf.find(i),[]) ss[self.uf.find(i)].append(i) ProgressBar.create(len(ss)) for _,v in sorted(ss.items(),key=lambda k: min(k[1])): ProgressBar.progress() minima = [] maxima = [] for i in v: mp_cur = self.mps[i] is_maximal = True is_minimal = True for j in v: if i == j: continue mp = self.mps[j] if mp_cur.mesh <= mp.mesh: is_maximal = False if mp.mesh <= mp_cur.mesh: is_minimal = False if is_maximal: maxima.append(mp_cur) if is_minimal: minima.append(mp_cur) for mn in minima: for mx in maxima: if mn.mesh <= mx.mesh: for add in subsets(list(mx.mesh - mn.mesh)): mid = mn.shade(set(add)) if self.uf.unite(self.mps[mn], self.mps[mid]): changed = True ProgressBar.finish() if not changed: break
def coincify(self, simultaneous=False): cnt = len(self.mps) n = self.mps.n sys.stderr.write('Shading lemma coincifier\n') ProgressBar.create(len(self.mps)) for mp in self.mps: ProgressBar.progress() poss = [] for (i,j) in mp.non_pointless_boxes(): # # Was # for i in range(n+1): # for j in range(n+1): for sh in mp.can_shade((i,j)): if simultaneous and (i,j) not in mp.mesh: poss.append((sh, set([(i,j)]))) if not simultaneous: self.uf.unite(self.mps[mp], self.mps[mp.shade((i,j))]) if simultaneous: for i in range(n+1): for j in range(n+1): for di in range(-1,2): for dj in range(-1,2): if (di == 0) == (dj == 0): continue i2,j2 = (i+di, j+dj) if 0 <= i2 < n+1 and 0 <= j2 < n+1: for sh in mp.can_shade2((i,j),(i2,j2)): poss.append((sh, set([(i,j),(i2,j2)]))) def bt(at, nm, used): if at == len(poss): mp2 = mp.shade(nm) self.uf.unite(self.mps[mp], self.mps[mp2]) return bt(at + 1, nm, used) if poss[at][0] not in used and not (nm & poss[at][1]): bt(at + 1, nm | poss[at][1], used | set([poss[at][0]])) bt(0, set(), set()) ProgressBar.finish()
print_clas = True binarypatterns = filter_binary(pattern_ranks, cpatt) if internal_check: sys.stderr.write("Internal checking\n") ProgressBar.create(len(binarypatterns)) for patt in binarypatterns: ProgressBar.progress() mpatt = MeshPatt.unrank(cpatt, patt) for length in range(len(cpatt), len(cpatt) * 2 + 2): for perm in perm_set.of_length(length): if perm.count_occurrences_of(mpatt) > 1: print("INTERNAL FAAAAAAAAAAAAAAAAAAAAAIIIIIIIIIIIIIIIIIIIIIIIIILLLLLLLLLLLLLLL") print(MeshPatt.unrank(cpatt, patt)) sys.exit(1) ProgressBar.finish() if external_check: for mpatt in gen_meshpatts(len(cpatt), cpatt): if mpatt.rank() in binarypatterns: continue if all(perm.count_occurrences_of(mpatt) == 1 for length in range(len(cpatt), len(cpatt) * 2 + 2) for perm in perm_set.of_length(length)): print("EXTERNAL FAAAAAAAAAAAAAAAAAAAAAIIIIIIIIIIIIIIIIIIIIIIIIILLLLLLLLLLLLLLL") print(MeshPatt.unrank(cpatt, mpatt)) sys.exit(1) if print_clas: sys.stdout.write("0\n") # print(sorted(binarypatterns)) sys.stdout.write('\n'.join(map(str, binarypatterns)) + '\n') # for patt in sorted(binarypatterns):
maxima = [] for cur in sorted(poss): if cur == last: continue add = True for other in poss: if cur < other: add = False if add: maxima.append(cur) last = cur for m in maxima: m = tuple(sorted(m)) mesh_perms.setdefault(m, []) mesh_perms[m].append(perm) ProgressBar.finish() curactive = set() cont = {} notcnt = 0 sys.stderr.write('Brute supersets, cnt = %d\n' % len(mps)) ProgressBar.create(len(mps)) for i in range(len(mps)): perms = set() here = mps[i] ProgressBar.progress() notcnt += 1 # print(i, here) for nxt in supersets_of_mesh(n+1, here.mesh): nxt = tuple(sorted(nxt)) if nxt in mesh_perms:
def brute_coincify_len(self, l, active): n = self.mps.n patt = self.mps.patt assert patt is not None cnt = len(self.mps) mesh_perms = {} sys.stderr.write('Permutations of length %d\n' % l) ProgressBar.create(factorial(l)) for perm in Permutations(l): ProgressBar.progress() poss = [] for res in containment(patt, perm): con = set(res) colcnt = 0 col = [-1]*len(perm) for i,v in enumerate(perm): if v in con: colcnt += 1 else: col[v-1] = colcnt rowcnt = 0 row = [-1]*len(perm) for v in range(len(perm)): if v+1 in con: rowcnt += 1 else: row[v] = rowcnt bad = set( (u,v) for u,v in zip(col,row) if u != -1 ) cur = set( (u,v) for u in range(len(patt)+1) for v in range(len(patt)+1) if (u,v) not in bad ) poss.append(cur) last = None maxima = [] for cur in sorted(poss): if cur == last: continue add = True for other in poss: if cur < other: add = False if add: maxima.append(cur) last = cur perm_id = get_perm_id(perm) for m in maxima: m = tuple(sorted(m)) mesh_perms.setdefault(m, []) mesh_perms[m].append(perm_id) ProgressBar.finish() max_shaded = {} for i in range(cnt): here = self.mps[i] if self.uf.find(i) not in max_shaded or len(here.mesh) > len(max_shaded[self.uf.find(i)]): max_shaded[self.uf.find(i)] = here cont = {} notcnt = 0 sys.stderr.write('Brute supersets, active = %d\n' % len(active)) ProgressBar.create(len(active)) for i in active: perms = set() here = max_shaded[i] ProgressBar.progress() notcnt += 1 # print(i, here) for nxt in supersets_of_mesh(n+1, here.mesh): nxt = tuple(sorted(nxt)) if nxt in mesh_perms: perms |= set(mesh_perms[nxt]) # print(i, perms) # perms = tuple([ tuple(p) for p in sorted(perms) ]) perms_id = get_perm_class_id(sorted(perms)) cont.setdefault(perms_id, []) cont[perms_id].append(i) ProgressBar.finish() for _, v in cont.items(): if len(v) == 1: active.remove(v[0]) return cont
def brute_coincify_len(l, active, contsets, singles): global mps global classpatt patt = classpatt assert patt is not None mesh_perms = {} sys.stderr.write('Permutations of length %d\n' % l) ProgressBar.create(factorial(l)) # For each permutation for perm in perm_set.of_length(l): ProgressBar.progress() poss = [] # loop over the occurrences of the underlying pattern exactly once for res in patt.occurrences_in(perm): con = set(perm[i] for i in res) colcnt = 0 col = [-1] * len(perm) for v in perm: if v in con: colcnt += 1 else: col[v] = colcnt rowcnt = 0 row = [-1] * len(perm) for v in range(len(perm)): if v in con: rowcnt += 1 else: row[v] = rowcnt # bad is the set of boxes that contain points and can not be shaded bad = set((u, v) for u, v in zip(col, row) if u != -1) # cur is the set of boxes that can be shaded cur = set((u, v) for u in range(len(patt) + 1) for v in range(len(patt) + 1) if (u, v) not in bad) poss.append(shad_to_binary(cur, len(patt) + 1)) last = None maxima = [] # compute the maximal sets of boxes that can be shaded for cur in sorted(poss): if cur == last: continue add = True for other in poss: if is_subset(cur, other) and cur != other: add = False break # pick out the maximal ones if add: maxima.append(cur) last = cur # for each maximal set, append the permutation to the list of # containing permutations any subset of the maximal set is then also # contained in the permutation perm_id = get_perm_id(perm) for m in maxima: mesh_perms.setdefault(m, []) mesh_perms[m].append(perm_id) ProgressBar.finish() cont = {} sys.stderr.write( 'Compare mesh patterns with occurrences, active = %d\n'.format( len(active))) ProgressBar.create(sum(map(len, active))) # For each active class for (mpatts, contset) in zip(active, contsets): # We monitor whether the class will split or not for i in mpatts: ProgressBar.progress() perms = set() for (maxi, ps) in mesh_perms.items(): if is_subset(mps[i], maxi): perms |= set(ps) permset_id = get_perm_class_id(tuple(sorted(perms))) permid_vec = contset + (permset_id, ) cont.setdefault(permid_vec, []) cont[permid_vec].append(i) ProgressBar.finish() nowactive = [] nowcontset = [] for cs, v in cont.items(): if len(v) > 1: nowactive.append(v) nowcontset.append(cs) else: singles.append(v[0]) return (nowactive, nowcontset)
def populate_rule_set(settings, rule_set): assert settings.sinput.is_classical # settings.logger.log('Generate allowed neighbors, overlap') # allowed_neighbors = find_allowed_neighbors(settings) settings.logger.log("Generate allowed neighbors, perm prop") allowed_neighbors_cpp = find_allowed_neighbors_classical_perm_prop(settings) ssets = set(settings.sets) n = settings.max_rule_size[0] m = settings.max_rule_size[1] for s in ssets: if type(s) is PointPermutationSet: pps = s break def generates_subset(rule): for l in range(settings.perm_bound + 1): for p in rule.generate_of_length(l, settings.sinput.permutations): if not settings.sinput.contains(p): return False return True # Special case: the empty rule rule_set.add_rule(GeneratingRule({(0, 0): None})) settings.logger.log("Generating point rules") valid = TrieMap() cur = [[[None for j in range(m)] for i in range(n)]] for i in range(n - 1, -1, -1): for j in range(m - 1, -1, -1): settings.logger.log("Cell (%d,%d)" % (i, j)) ProgressBar.create(len(cur)) nxt = [] for rule in cur: ProgressBar.progress() left = settings.max_non_empty - sum(rule[x][y] is not None for x in range(n) for y in range(m)) at_most = settings.mn_at_most - sum( 0 if rule[x][y] is None else rule[x][y].min_length(settings.sinput.permutations) for x in range(n) for y in range(m) ) ss = set([None, pps]) for s in ss: if s is not None: if left == 0 or s.min_length(settings.sinput.permutations) > at_most: continue rule[i][j] = s if j == 0: found = False for y in range(m): if rule[i][y] is not None: found = True break if not found: continue if rule[i][j] is not None and not generates_subset(GeneratingRule(rule)): continue is_done = True for x in range(i, n): for y in range(j): if rule[x][y] is not None: is_done = False break if not is_done: break if is_done: for y in range(j, m): found = False for x in range(i, n): if rule[x][y] is not None: found = True break if not found: is_done = False break if is_done and any(rule[i][y] is not None for y in range(j, m)): key = [ (x, y, pps) for x in range(n - 1, -1, -1) for y in range(m - 1, -1, -1) if rule[x][y] is not None ] valid[key] = True si = i sj = None for y in range(m): found = False for x in range(si, n): if rule[x][y] is not None: found = True break if found: sj = y break assert sj is not None g = GeneratingRule({(x - si, y - sj): rule[x][y] for x in range(si, n) for y in range(sj, m)}) ok = True if (si, sj) == (n - 1, m - 1) and not rule[si][sj].can_be_alone(): ok = False if ok: assert rule_set.add_rule(g) != RuleDeath.PERM_PROP nxt.append([[rule[x][y] for y in range(m)] for x in range(n)]) cur = nxt ProgressBar.finish() dag = settings.dag.get_transitive_reduction() order = dag.get_topological_order() settings.logger.log("Number of elements: %d" % len(order)) ProgressBar.create(len(order) - 2) for s in order: if s is None or type(s) is PointPermutationSet: continue ProgressBar.clear() settings.logger.log("Promoting to: %s" % (s.description if s is not None else "empty set")) ProgressBar.draw() ProgressBar.draw() above = {a for a in dag.get_parents(s) if a is not None and a != s} rule = [[None for y in range(m)] for x in range(n)] def intersect(cur, pos): if settings.filter_rule_incrementally and not generates_subset(GeneratingRule(rule)): return None here = TrieNode() here.end = all(c.end for c in cur) if here.end: si = pos[0] sj = None for y in range(m): found = False for x in range(si, n): if rule[x][y] is not None: found = True break if found: sj = y break assert sj is not None g = GeneratingRule({(x - si, y - sj): rule[x][y] for x in range(si, n) for y in range(sj, m)}) ok = True if (si, sj) == (n - 1, m - 1) and not rule[si][sj].can_be_alone(): ok = False if ok: res = rule_set.add_rule(g) if res == RuleDeath.PERM_PROP: return None elif res != RuleDeath.ALIVE: here.end = False found = False for (i, j, s2) in reduce(lambda x, y: x & y, [set(c.down.keys()) for c in cur]): rule[i][j] = s2 ok = True if ok: # make sure the current type is an allowed neighbor of all (not necessarily immediate) neighbors for ci in range(i, n): for cj in range(m): if (ci, cj) > (i, j): di = signum(ci - i) dj = signum(cj - j) if s2 not in allowed_neighbors_cpp[(rule[ci][cj], -di, -dj)]: ok = False break if not ok: break if ok and type(s2) is not PointPermutationSet: # check if any of my immediate neighbors are neither empty nor a point # in that case, we can only put a point in the current box for di in range(-1, 2): for dj in range(-1, 2): ci, cj = i + di, j + dj if (ci, cj) > (i, j) and 0 <= ci < n and 0 <= cj < m: if rule[ci][cj] is not None and type(rule[ci][cj]) is not PointPermutationSet: ok = False break if not ok: break if ok: rest = intersect([c.down[(i, j, s2)] for c in cur], (i, j)) if rest is not None: found = True here.down[(i, j, s2)] = rest rule[i][j] = None if not found and not here.end: return None return here def promote(cur): for ((i, j, s2), nxt) in cur.down.items(): rule[i][j] = s2 promote(nxt) rule[i][j] = None add = {} for ((i, j, s2), nxt) in cur.down.items(): rule[i][j] = s cur_mn = sum( 0 if rule[x][y] is None else rule[x][y].min_length(settings.sinput.permutations) for x in range(n) for y in range(m) ) if cur_mn <= settings.mn_at_most and s2 in above and (i, j, s) not in cur.down and (i, j, s) not in add: if all((i, j, a) in cur.down for a in above): ok = True if ok: # make sure the current type is an allowed neighbor of all (not necessarily immediate) neighbors for ci in range(i, n): for cj in range(m): if (ci, cj) > (i, j): di = signum(ci - i) dj = signum(cj - j) if s not in allowed_neighbors_cpp[(rule[ci][cj], -di, -dj)]: ok = False break if not ok: break if ok: # check if any of my immediate neighbors are neither empty nor a point # in that case, we can only put a point in the current box for di in range(-1, 2): for dj in range(-1, 2): ci, cj = i + di, j + dj if (ci, cj) > (i, j) and 0 <= ci < n and 0 <= cj < m: if rule[ci][cj] is not None and type(rule[ci][cj]) is not PointPermutationSet: ok = False break if not ok: break if ok: add[(i, j, s)] = intersect([cur.down[(i, j, a)] for a in above], (i, j)) rule[i][j] = None for (k, v) in add.items(): if v is not None: cur.down[k] = v promote(valid.root) ProgressBar.progress() ProgressBar.finish()