import proveit
from proveit import ExprRange, ExprTuple, Function, IndexedVar
from proveit import a, b, c, k, m, n, x, y, A, B, C
from proveit.logic import Equals, InSet, Or, Boolean
from proveit.logic.booleans.disjunction import or_if_any
from proveit.logic.sets.enumeration import enum_set_def
from proveit.logic.sets.enumeration import fold
from proveit.numbers import Add, subtract
from proveit.numbers import zero, one, two, three, Neg, Complex, Natural, NaturalPos
from proveit.core_expr_types import a_1_to_m, c_1_to_n, x_1_to_n, y_1_to_n
theory = proveit.Theory() # the theorem's theory
%proving in_enumerated_set
enum_set_def
enum_set_def_with_k = enum_set_def.instantiate({n:k}, assumptions=[InSet(k, Natural)], num_forall_eliminations=0,
auto_simplify=False)
# this also works, first instantiating, then generalizing over the new var
# enum_set_def_inst_n_to_k = enum_set_def.instantiate({n:k}, assumptions=[InSet(k, Natural)])
# enum_set_def_with_k = enum_set_def_inst_n_to_k.generalize([[k]], [[Natural]])
enum_set_def_with_k_inst = enum_set_def_with_k.instantiate(
{k:k, x:b, y:ExprTuple(a_1_to_m, b, c_1_to_n)},
assumptions=[InSet(k, Natural), InSet(m, Natural), InSet(n, Natural), InSet(Add(subtract(m, one), one), Natural), Equals(Add(m, one, n), k)],
auto_simplify=False)
enum_set_def_with_k_inst.expr.rhs
or_if_any
A_sub, C_sub = (
ExprRange(k, Equals(b, IndexedVar(a, k)), one, m),
ExprRange(k, Equals(b, IndexedVar(c, k)), one, n))
A_in_Bool_assumptions, C_in_Bool_assumptions = (
ExprRange(k, InSet(Equals(b, IndexedVar(a, k)), Boolean), one, m),
ExprRange(k, InSet(Equals(b, IndexedVar(c, k)), Boolean), one, n))
or_if_any_inst = or_if_any.instantiate(
{m:m, n:n, A:A_sub, B:Equals(b,b), C:C_sub},
assumptions=[InSet(m, Natural), InSet(n, Natural),
A_in_Bool_assumptions, C_in_Bool_assumptions])
the_or_expr = Or(Equals(b, b),
ExprRange(
k,
Equals(b, IndexedVar(a, k)),
one, m))
another_or_expr = Or(Equals(b, a), Equals(b, b), Equals(b, c))
another_or_expr.associate(1, 2)
the_operands = the_or_expr.operands
or_if_any
A_sub, C_sub = (
ExprRange(k, Equals(b, IndexedVar(a, k)), one, m),
ExprRange(k, Equals(b, IndexedVar(c, k)), one, n))
A_in_Bool_assumptions, B_in_Bool_assumptions = (
ExprRange(k, InSet(Equals(b, IndexedVar(a, k)), Boolean), one, m),
ExprRange(k, InSet(Equals(b, IndexedVar(c, k)), Boolean), one, n))
# why are the equalities having to be ASSUMED to be in Boolean?
Equals(b, IndexedVar(a, one)).deduce_in_bool()
or_if_any_inst = or_if_any.instantiate(
{m:m, n:n, A:A_sub, B:Equals(b,b), C:C_sub},
assumptions=[InSet(m, Natural), InSet(n, Natural), A_in_Bool_assumptions, B_in_Bool_assumptions])
A_in_Bool_assumptions = ExprRange(k, InSet(Equals(b, IndexedVar(a, k)), Boolean), one, m)
# Or(Equals(b, b),
# ExprRange(
# k,
# Equals(b, IndexedVar(a, k)),
# one, m)).conclude_via_example(Equals(b, b),
# assumptions=[ExprRange(k, InSet(Equals(b, IndexedVar(a, k)), Boolean), one, m)])
# Example to help construct a multi-Or of equalities
# Or(ExprRange(k, Equals(IndexedVar(x, k), Function(f, Add(i, k))),
# zero, subtract(j, i)))
# Or(ExprRange(
# k,
# Equals(b, IndexedVar(a, k)),
# one, m),
# Equals(b, b),
# ExprRange(
# k,
# Equals(b, IndexedVar(c, k)),
# one, n)).prove()
enum_set_def_inst = enum_set_def.instantiate(
{n:n, x:b}, assumptions=[InSet(n, Natural)])
fold