import proveit
theory = proveit.Theory() # the theorem's theory
from proveit import defaults
from proveit import a, b, c, d, m
from proveit.core_expr_types.tuples import tuple_eq_def
from proveit.logic import And
from proveit.numbers import Add, zero, one
from proveit.numbers.number_sets.natural_numbers import fold_forall_natural_pos
%proving tuple_eq_via_elem_eq
tuple_eq_via_elem_eq.instance_expr
fold_forall_natural_pos
from proveit import Function
from proveit import P, i
induction_inst = \
fold_forall_natural_pos.instantiate({Function(P, i):tuple_eq_via_elem_eq.instance_expr}) \
.inner_expr().with_wrapping_at(1).inner_expr().antecedent.with_wrapping_at(1) \
.inner_expr().antecedent.operands[1].with_wrapping()
induction_base = induction_inst.antecedent.operands[0]
a1, b1 = induction_base.instance_params
tuple_eq_def
tuple_eq_base = tuple_eq_def.instantiate({i:zero})
tuple_eq_base_inst = tuple_eq_base.instantiate({b:a1, d:b1})
tuple_eq_base_inst.rhs.prove(assumptions=induction_base.conditions)
tuple_eq_base_inst.derive_left_via_equality(assumptions=induction_base.conditions)
induction_base.prove()
induction_step = induction_inst.antecedent.operands[1].with_wrapping()
eq_conds = induction_step.instance_expr.explicit_conditions()[0]
defaults.assumptions = (induction_step.conditions + [eq_conds])
induction_hyp = induction_step.conditions[1]
Splitting apart the conjunction of equality conditions is an important step
eq_cond_partition = eq_conds.partition(m)
eq_conds_conjunction = And(eq_conds).prove()
eq_conds_conjunction_partition = eq_cond_partition.sub_right_side_into(eq_conds_conjunction)
eq_conds_conjunction_partition.derive_some(0)
Now we can instantiate the induction hypothesis
induction_hyp.instantiate()
And now we will be able to prove the induction step by invoking the tuple_eq_def
axiom
last_eq = eq_conds_conjunction_partition.derive_any(1)
a_mp1, b_mp1 = last_eq.operands
tuple_eq_def
tuple_eq_def_inst = tuple_eq_def.instantiate({i:m, c:b, b:a_mp1, d:b_mp1})
tuple_eq_def_inst.rhs.prove()
tuple_eq_split_both = tuple_eq_def_inst.derive_left_via_equality()
tuple_eq_split_right = tuple_eq_split_both.inner_expr().lhs.merge()
tuple_eq = tuple_eq_split_right.inner_expr().rhs.merge()
induction_step.prove()
induction_inst.derive_consequent()
%qed