Skip to content

Commit

Permalink
remove backtracking as it is subsumed by other checks and is expensive
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewcropper committed Dec 21, 2024
1 parent e94c00f commit 2c3fac4
Showing 1 changed file with 150 additions and 150 deletions.
300 changes: 150 additions & 150 deletions popper/loop.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,8 +168,8 @@ def run(self, bkcons):

scores = self.scores = {}

could_prune_later = self.could_prune_later = []
could_prune_later_rec = self.could_prune_later_rec = []
# could_prune_later = self.could_prune_later = []
# could_prune_later_rec = self.could_prune_later_rec = []

to_combine = set()

Expand Down Expand Up @@ -495,11 +495,11 @@ def run(self, bkcons):
if tp < min_coverage:
add_spec = True

if not add_spec and not pruned_more_general:
if is_recursive:
could_prune_later_rec.append((prog, pos_covered, prog_size))
else:
could_prune_later.append((prog, pos_covered, prog_size))
# if not add_spec and not pruned_more_general:
# if is_recursive:
# could_prune_later_rec.append((prog, pos_covered, prog_size))
# else:
# could_prune_later.append((prog, pos_covered, prog_size))

add_to_combiner = False
if settings.noisy and not skipped and not skip_early_neg and not is_recursive and not has_invention and tp > prog_size+fp and fp+prog_size < settings.best_mdl and not noisy_subsumed:
Expand Down Expand Up @@ -1348,203 +1348,203 @@ def subsumed_or_covers_too_few(self, prog, seen=set()):
return out


def prune_subsumed_backtrack(self, pos_covered, prog_size):
could_prune_later, could_prune_later_rec, tester, settings = self.could_prune_later, self.could_prune_later_rec, self.tester, self.settings
to_prune = set()
to_delete = set()
to_delete_rec = set()
seen = set()
pruned2 = self.pruned2

for index, (prog2, pos_covered2, prog2_size) in enumerate(could_prune_later_rec):
# AC: TODO: separate this check
# should_prune = check_coverage and len(pos_covered2) == 1
if subset(pos_covered2, pos_covered):
# print('PRUNE!!!')
# print(format_prog(prog2))
# TODO: FIND MOST GENERAL SUBSUMED PROGRAM
to_delete_rec.add(index)
to_prune.add(prog2)
# elif self.check_subsumed_by_two(pos_covered2, calc_prog_size(prog2)):
# print('PRUNE!!!')
# print(format_prog(prog2))
# def prune_subsumed_backtrack(self, pos_covered, prog_size):
# could_prune_later, could_prune_later_rec, tester, settings = self.could_prune_later, self.could_prune_later_rec, self.tester, self.settings
# to_prune = set()
# to_delete = set()
# to_delete_rec = set()
# seen = set()
# pruned2 = self.pruned2

# for index, (prog2, pos_covered2, prog2_size) in enumerate(could_prune_later_rec):
# # AC: TODO: separate this check
# # should_prune = check_coverage and len(pos_covered2) == 1
# if subset(pos_covered2, pos_covered):
# # print('PRUNE!!!')
# # print(format_prog(prog2))
# # TODO: FIND MOST GENERAL SUBSUMED PROGRAM
# to_delete_rec.add(index)
# to_prune.add(prog2)
# # elif self.check_subsumed_by_two(pos_covered2, calc_prog_size(prog2)):
# # print('PRUNE!!!')
# # print(format_prog(prog2))

for index, (prog2, pos_covered2, prog2_size) in enumerate(could_prune_later):

subsumed = subset(pos_covered2, pos_covered)
subsumed_by_two = False
if not subsumed:
# subsumed_by_two = self.check_subsumed_by_two(pos_covered2, prog2_size)
subsumed_by_two = self.check_subsumed_by_two_v2(prog_size, prog2_size, pos_covered, pos_covered2)
# for index, (prog2, pos_covered2, prog2_size) in enumerate(could_prune_later):

if not (subsumed or subsumed_by_two):
if pos_covered2.count(1) < settings.min_coverage:
print(pos_covered2.count(1), settings.min_coverage)
assert(False)
continue
# subsumed = subset(pos_covered2, pos_covered)
# subsumed_by_two = False
# if not subsumed:
# # subsumed_by_two = self.check_subsumed_by_two(pos_covered2, prog2_size)
# subsumed_by_two = self.check_subsumed_by_two_v2(prog_size, prog2_size, pos_covered, pos_covered2)

head, body = tuple(prog2)[0]
# if not (subsumed or subsumed_by_two):
# if pos_covered2.count(1) < settings.min_coverage:
# print(pos_covered2.count(1), settings.min_coverage)
# assert(False)
# continue

seen.add(body)
# head, body = tuple(prog2)[0]

# If we have seen a subset of the body then ignore this program
if any(frozenset(x) in pruned2 for x in non_empty_powerset(body)):
to_delete.add(index)
continue
# seen.add(body)

pruned_subprog = False
# # If we have seen a subset of the body then ignore this program
# if any(frozenset(x) in pruned2 for x in non_empty_powerset(body)):
# to_delete.add(index)
# continue

# We now enumerate the subsets of the body of this role to find the most general subsumed subset
for new_body in non_empty_subset(body):
new_rule = (head, new_body)
# pruned_subprog = False

if not head_connected(new_rule):
continue
# # We now enumerate the subsets of the body of this role to find the most general subsumed subset
# for new_body in non_empty_subset(body):
# new_rule = (head, new_body)

if not self.has_valid_directions(new_rule):
continue
# if not head_connected(new_rule):
# continue

tmp = frozenset(new_body)
if tmp in seen:
continue
seen.add(tmp)
# if not self.has_valid_directions(new_rule):
# continue

new_prog = frozenset([new_rule])
# tmp = frozenset(new_body)
# if tmp in seen:
# continue
# seen.add(tmp)

if tester.has_redundant_literal(new_prog):
continue
# new_prog = frozenset([new_rule])

sub_prog_pos_covered = tester.get_pos_covered(new_prog)
# if tester.has_redundant_literal(new_prog):
# continue

sub_prog_subsumed = sub_prog_pos_covered == pos_covered2
# sub_prog_pos_covered = tester.get_pos_covered(new_prog)

sub_subsumed_by_two = not sub_prog_subsumed and self.check_subsumed_by_two(sub_prog_pos_covered, calc_prog_size(new_prog))
# sub_prog_subsumed = sub_prog_pos_covered == pos_covered2

if self.settings.showcons:
if sub_prog_subsumed:
print('\t', 'SUBSUMED BACKTRACK (GENERALISATION):', '\t', format_prog(new_prog))
elif sub_subsumed_by_two:
print('\t', 'SUBSUMED BY TWO BACKTRACK (GENERALISATION):', '\t', format_prog(new_prog))
# sub_subsumed_by_two = not sub_prog_subsumed and self.check_subsumed_by_two(sub_prog_pos_covered, calc_prog_size(new_prog))

if sub_prog_subsumed or sub_subsumed_by_two:
to_prune.add(new_prog)
pruned_subprog = True
for x in self.find_variants(remap_variables(new_rule)):
pruned2.add(x)
break
# if self.settings.showcons:
# if sub_prog_subsumed:
# print('\t', 'SUBSUMED BACKTRACK (GENERALISATION):', '\t', format_prog(new_prog))
# elif sub_subsumed_by_two:
# print('\t', 'SUBSUMED BY TWO BACKTRACK (GENERALISATION):', '\t', format_prog(new_prog))

to_delete.add(index)
# if sub_prog_subsumed or sub_subsumed_by_two:
# to_prune.add(new_prog)
# pruned_subprog = True
# for x in self.find_variants(remap_variables(new_rule)):
# pruned2.add(x)
# break

if pruned_subprog:
continue
# to_delete.add(index)

for x in self.find_variants(remap_variables((head, body))):
pruned2.add(x)
# if pruned_subprog:
# continue

if self.settings.showcons:
if subsumed:
print('\t', 'SUBSUMED BACKTRACK:', '\t', format_prog(prog2))
elif subsumed_by_two:
print('\t', 'SUBSUMED BY TWO BACKTRACK:', '\t', format_prog(prog2))
to_prune.add(prog2)
# for x in self.find_variants(remap_variables((head, body))):
# pruned2.add(x)

for i in sorted(to_delete_rec, reverse=True):
del could_prune_later_rec[i]
# if self.settings.showcons:
# if subsumed:
# print('\t', 'SUBSUMED BACKTRACK:', '\t', format_prog(prog2))
# elif subsumed_by_two:
# print('\t', 'SUBSUMED BY TWO BACKTRACK:', '\t', format_prog(prog2))
# to_prune.add(prog2)

for i in sorted(to_delete, reverse=True):
del could_prune_later[i]
# for i in sorted(to_delete_rec, reverse=True):
# del could_prune_later_rec[i]

return to_prune
# for i in sorted(to_delete, reverse=True):
# del could_prune_later[i]

def prune_subsumed_backtrack_specialcase(self):
could_prune_later, tester, settings = self.could_prune_later, self.tester, self.settings
to_prune = set()
to_delete = set()
seen = set()
pruned2 = self.pruned2
# return to_prune

if not settings.solution_found:
return
# def prune_subsumed_backtrack_specialcase(self):
# could_prune_later, tester, settings = self.could_prune_later, self.tester, self.settings
# to_prune = set()
# to_delete = set()
# seen = set()
# pruned2 = self.pruned2

for index, (prog2, pos_covered2, prog2_size) in enumerate(could_prune_later):
# if not settings.solution_found:
# return

if len(prog2) > 1:
assert(False)
# continue
# for index, (prog2, pos_covered2, prog2_size) in enumerate(could_prune_later):

# if len(prog2) > 1:
# assert(False)
# # continue

covers_too_few = pos_covered2.count(1) < settings.min_coverage

if not covers_too_few:
covers_too_few = self.check_covers_too_few(calc_prog_size(prog2), pos_covered2)
# covers_too_few = pos_covered2.count(1) < settings.min_coverage

if not covers_too_few:
continue
# if not covers_too_few:
# covers_too_few = self.check_covers_too_few(calc_prog_size(prog2), pos_covered2)

head, body = tuple(prog2)[0]
# if not covers_too_few:
# continue

seen.add(body)
# head, body = tuple(prog2)[0]

# If we have seen a subset of the body then ignore this program
if any(frozenset(x) in pruned2 for x in non_empty_powerset(body)):
to_delete.add(index)
continue
# seen.add(body)

pruned_subprog = False
# # If we have seen a subset of the body then ignore this program
# if any(frozenset(x) in pruned2 for x in non_empty_powerset(body)):
# to_delete.add(index)
# continue

# We now enumerate the subsets of the body of this role to find the most general subsumed subset
for new_body in non_empty_subset(body):
new_rule = (head, new_body)
# pruned_subprog = False

if not head_connected(new_rule):
continue
# # We now enumerate the subsets of the body of this role to find the most general subsumed subset
# for new_body in non_empty_subset(body):
# new_rule = (head, new_body)

if not self.has_valid_directions(new_rule):
continue
# if not head_connected(new_rule):
# continue

tmp = frozenset(new_body)
if tmp in seen:
continue
seen.add(tmp)
# if not self.has_valid_directions(new_rule):
# continue

new_prog = frozenset([new_rule])
# tmp = frozenset(new_body)
# if tmp in seen:
# continue
# seen.add(tmp)

if tester.has_redundant_literal(new_prog):
continue
# new_prog = frozenset([new_rule])

sub_prog_pos_covered = tester.get_pos_covered(new_prog)
# if tester.has_redundant_literal(new_prog):
# continue

sub_covers_too_few = sub_prog_pos_covered.count(1) < settings.min_coverage
# sub_prog_pos_covered = tester.get_pos_covered(new_prog)

if not sub_covers_too_few:
sub_covers_too_few = self.check_covers_too_few(calc_prog_size(new_prog), sub_prog_pos_covered)
# sub_covers_too_few = sub_prog_pos_covered.count(1) < settings.min_coverage

if sub_covers_too_few:
if self.settings.showcons:
print('\t', 'COVERS TOO FEW BACKTRACK (GENERALISATION)', '\t', format_prog(new_prog))
to_prune.add(new_prog)
pruned_subprog = True
for x in self.find_variants(remap_variables(new_rule)):
pruned2.add(x)
break
# if not sub_covers_too_few:
# sub_covers_too_few = self.check_covers_too_few(calc_prog_size(new_prog), sub_prog_pos_covered)

to_delete.add(index)
# if sub_covers_too_few:
# if self.settings.showcons:
# print('\t', 'COVERS TOO FEW BACKTRACK (GENERALISATION)', '\t', format_prog(new_prog))
# to_prune.add(new_prog)
# pruned_subprog = True
# for x in self.find_variants(remap_variables(new_rule)):
# pruned2.add(x)
# break

if pruned_subprog:
continue
# to_delete.add(index)

# if pruned_subprog:
# continue

for x in self.find_variants(remap_variables((head, body))):
pruned2.add(x)
# for x in self.find_variants(remap_variables((head, body))):
# pruned2.add(x)

if self.settings.showcons:
print('\t', 'COVERS TOO FEW BACKTRACK', '\t', format_prog(prog2))
to_prune.add(prog2)
# if self.settings.showcons:
# print('\t', 'COVERS TOO FEW BACKTRACK', '\t', format_prog(prog2))
# to_prune.add(prog2)

for i in sorted(to_delete, reverse=True):
del could_prune_later[i]
# for i in sorted(to_delete, reverse=True):
# del could_prune_later[i]

return to_prune
# return to_prune

def find_variants(self, rule):
head, body = rule
Expand Down

0 comments on commit 2c3fac4

Please sign in to comment.