class_docstr: Rules that describe how to deduce facts in logic space
  
  When defined, these rules allow implications to quickly be determined
  for a set of facts. For this precomputed deduction tables are used.
  see `deduce_all_facts`   (forward-chaining)
  
  Also it is possible to gather prerequisites for a fact, which is tried
  to be proven.    (backward-chaining)
  
  
  Definition Syntax
  -----------------
  
  a -> b       -- a=T -> b=T  (and automatically b=F -> a=F)
  a -> !b      -- a=T -> b=F
  a == b       -- a -> b & b -> a
  a -> b & c   -- a=T -> b=T & c=T
  # TODO b | c
  
  
  Internals
  ---------
  
  .full_implications[k, v]: all the implications of fact k=v
  .beta_triggers[k, v]: beta rules that might be triggered when k=v
  .prereq  -- {} k <- [] of k's prerequisites
  
  .defined_facts -- set of defined fact names
docstr: Returns a generator with lines to represent the facts and rules 
docstr_tok: ["Returns","a","generator","with","lines","to","represent","the","facts","and","rules"]
code: def print_rules(self) -> Iterator[str]:
      """Returns a generator with lines to represent the facts and rules"""
      yield from self._defined_facts_lines()
      yield ""
      yield ""
      yield from self._full_implications_lines()
      yield ""
      yield ""
      yield from self._prereq_lines()
      yield ""
      yield ""
      yield from self._beta_rules_lines()
      yield ""
      yield ""
      yield "generated_assumptions = {'defined_facts': defined_facts, 'full_implications': full_implications,"
      yield "               'prereq': prereq, 'beta_rules': beta_rules, 'beta_triggers': beta_triggers}"
  
imports: from collections import defaultdict
  from typing import Iterator
  from .logic import Logic, And, Or, Not
label_desc: Use image node_id 8 for calling the FactRules obj's underlying member method code with example usage: obj.print_rules() without return types