I monkey-patched popper.util.format_rule as follows:
def format_rule(rule):
head, body = rule
head_str = ''
if head:
head_str = popper.util.format_literal(head)
body_list = [popper.util.format_literal(literal) for literal in body]
body_str = ','.join(sorted(body_list))
return f'{head_str}:- {body_str}.'
popper.util.format_rule = format_rule
This means that when Popper prints a rule, the body is produced in lexicographic order. This is potentially expensive in terms of memory allocation and cycles, but means that in tests one can capture the logs and match output more easily.
I could incorporate this in util.py and provide a PR, but I didn't want to do that w/o explicit OK because of the potential efficiency impact. On the other hand, if the hypotheses are not dumped when running for performance, this would be benign.