def all(self, *args): if len(args) == 1: return args[0] fv, qv = set(), set() for a in args: assert wff.is_well_formed_formula(a) fv |= wff.get_free_variables(a) qv |= wff.get_quantified_variables(a) assert not (qv & fv) return u'<%s∧%s>' % (args[0], self.all(*args[1:]))
def is_valid_by_double_tilde(self, s): s = U(s) if not wff.is_well_formed_formula(s): return False for theorem in self.theorems: if self.is_removal_of_double_tilde( s, theorem) or self.is_removal_of_double_tilde(theorem, s): return True return False
def is_valid_by_separation(self, s): s = U(s) if not wff.is_well_formed_formula(s): return False for theorem in self.theorems: if theorem[0] == '<' and theorem[-1] == '>': if theorem.startswith(u'<%s∧' % s): return True if theorem.endswith(u'∧%s>' % s): return True return False
def abs_kth_term_is_x(self, a, b, k, x): # The finite sequence "AB" is defined as # AB(0) = a mod (b+1) # AB(1) = a mod (2b+1) # AB(2) = a mod (3b+1) # ... # According to http://math.stackexchange.com/a/312915/121469, # any finite sequence can be represented in this way for at least one pair (a,b). result = self.a_mod_b_equals_c(a, u'S({b}⋅S{k})'.format(**locals()), x) assert wff.is_well_formed_formula(result) return result
def _is_valid_by_substituting(self, s, a, b): s = U(s) for xi in range(0, len(s)): for xj in range(xi + 1, len(s)): x = s[xi:xj] if wff.is_well_formed_formula(x): for yi in range(0, len(s)): for yj in range(yi + 1, len(s)): y = s[yi:yj] if wff.is_well_formed_formula(y): first = a.replace('X', x).replace('Y', y) if len(first) > len(s): continue second = b.replace('X', x).replace('Y', y) i = s.find(first) while i != -1: substituted_s = s[:i] + second + s[ i + len(first):] if substituted_s in self.theorems: return True i = s.find(first, i + 1) return False
def is_valid_by_induction(self, s): s = U(s) if wff.is_well_formed_formula(s) and s[0] == u'∀': colon = s.find(':') assert colon >= 0 u, x = s[1:colon], s[colon + 1:] assert is_variable(u) base_case = x.replace(u, '0') if base_case in self.theorems: inductive_case = u'∀%s:<%s⊃%s>' % (u, x, x.replace(u, 'S' + u)) if inductive_case in self.theorems: return True return False
f.step('∃b:b=Sb') # specification (Wrong!) assert False except InvalidStep: pass # Exercise, page 220: Derive "Different numbers have different successors" as a theorem of TNT. d = Derivation() with d.fantasy('Sa=Sb') as f: f.step('a=b') d.step('<Sa=Sb⊃a=b>') d.step('<~a=b⊃~Sa=Sb>') d.step('∀b:<~a=b⊃~Sa=Sb>') d.step('∀a:∀b:<~a=b⊃~Sa=Sb>') # Page 221: Something Is Missing assert is_well_formed_formula('∀a:(0+a)=a') assert is_well_formed_formula('~∀a:(0+a)=a') # Page 224: Induction d = Derivation() d.step('∀a:∀b:(a+Sb)=S(a+b)') # axiom 3 d.step('∀b:(0+Sb)=S(0+b)') # specification d.step('(0+Sb)=S(0+b)') # specification with d.fantasy('(0+b)=b') as f: f.step('S(0+b)=Sb') # add S f.step('(0+Sb)=S(0+b)') # carry over line 3 f.step('(0+Sb)=Sb') # transitivity d.step('<(0+b)=b⊃(0+Sb)=Sb>') # fantasy rule d.step('∀b:<(0+b)=b⊃(0+Sb)=Sb>') # generalization d.step('(0+0)=0') # specialization of axiom 2 d.step('∀b:(0+b)=b') # induction
@allocates_only_quantified_variables def t_mod_3_is_0(self, t): self.do_not_allocate_variables_in_terms(t) x = self.reg() return u'∃{x}:(SSS0⋅{x})={t}'.format(**locals()) @allocates_only_quantified_variables def mumon(self): return self.s_is_derivable_from_t( self.numeral(self.godel_number('MU')), self.numeral(self.godel_number('MI'))) if __name__ == '__main__': assert wff.is_well_formed_formula( MIUEncoder().s_is_directly_derivable_from_t(u's', u't')) assert wff.is_well_formed_formula(MIUEncoder().s_is_derivable_from_t( u's', u't')) b_is_a_power_of_10 = u'∃c:' + Encoder().a_raised_to_b_is_c( Encoder().numeral(10), 'c', 'b') print 'A TNT expression encoding the statement "b is a power of 10" is:' print b_is_a_power_of_10 assert wff.is_well_formed_formula(b_is_a_power_of_10) print 'Computing MUMON...' mumon = MIUEncoder().mumon() print mumon e = MIUEncoder() print 'Lemma 1 for proving MU underivable:'