import proveit
from proveit import defaults
from proveit import Judgment
from proveit.logic.sets import EmptySet
from proveit.logic.sets.cardinality import empty_card
from proveit import Operation, IndexedVar
from proveit.logic import Forall, InSet, Or, Boolean, in_bool, And
from proveit import A, B, Q, x, i, l, m, n, P,S
from proveit.core_expr_types import A_1_to_m
from proveit.numbers import num, Exp, Add, one, Natural, Less, zero, greater
from proveit.numbers.number_sets.natural_numbers import fold_forall_natural_pos
#from proveit.numbers.number_sets.integers import empty_nat_def
from proveit.logic.booleans.disjunction import multi_disjunction_def, empty_disjunction
from proveit.logic.booleans.disjunction import binary_closure
theory = proveit.Theory() # the theorem's theory
%proving closure
closure.instance_expr
fold_forall_natural_pos
from proveit import Function
from proveit import P, m
induction_inst = \
fold_forall_natural_pos.instantiate({Function(P, m):closure.instance_expr})
induction_base = induction_inst.antecedent.operands[0]
induction_base.prove()
induction_step = induction_inst.antecedent.operands[1]
in_bool_conds = induction_step.instance_expr.conditions[0]
defaults.assumptions = (induction_step.conditions + [in_bool_conds])
induction_hyp = induction_step.conditions[1]
Splitting apart the conjunction of "in Bool" conditions is an important step
in_bool_cond_partition = in_bool_conds.partition(m)
in_bool_conds_conjunction = And(in_bool_conds).prove()
in_bool_conds_conjunction_partition = \
in_bool_cond_partition.sub_right_side_into(in_bool_conds_conjunction)
in_bool_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 via binary_closure and multi_disjunction_def
last_in_bool_cond = in_bool_conds_conjunction_partition.derive_any(1)
A_mp1 = last_in_bool_cond.element
binary_closure
binary_conclusion = binary_closure.instantiate({A:Or(A_1_to_m), B:A_mp1})
multi_disjunction_eq = multi_disjunction_def.instantiate({B:A_mp1})
pre_merge_conclusion = multi_disjunction_eq.sub_left_side_into(binary_conclusion)
pre_merge_conclusion.inner_expr().element.operands.merge()
induction_step
induction_step.prove()
induction_inst.derive_consequent()
%qed