def substitution(self, replacement, assumptions=USE_DEFAULTS): ''' Equate the top level expression with a similar expression with the inner expression replaced by the replacement. ''' from proveit.logic import Equals cur_inner_expr = self.expr_hierarchy[-1] equality = Equals(cur_inner_expr, replacement).prove(assumptions) equality.substitution(self.repl_lambda(), assumptions=assumptions)
def test(): substitution.specialize({fx:Not(x), x:a, y:b}, assumptions=[Equals(a, b)]) expr = Equals(a, Add(b, Frac(c, d), Exp(c, d))) gRepl = Lambda.globalRepl(expr, d) d_eq_y = Equals(d, y) d_eq_y.substitution(gRepl, assumptions=[d_eq_y]) d_eq_y.substitution(expr, assumptions=[d_eq_y]) d_eq_y.substitution(expr, assumptions=[d_eq_y]).proof() innerExpr = expr.innerExpr() innerExpr = innerExpr.rhs innerExpr = innerExpr.operands[1] innerExpr = innerExpr.denominator d_eq_y.substitution(innerExpr, assumptions=[d_eq_y]) d_eq_y.substitution(expr.innerExpr().rhs.operands[2].exponent, assumptions=[d_eq_y]) d_eq_y.subRightSideInto(gRepl, assumptions=[d_eq_y,expr]) d_eq_y.subRightSideInto(expr, assumptions=[d_eq_y,expr]) y_eq_d = Equals(y, d) y_eq_d.subLeftSideInto(gRepl, assumptions=[y_eq_d,expr]) y_eq_d.subLeftSideInto(expr, assumptions=[y_eq_d,expr]) y_eq_d.subLeftSideInto(expr, assumptions=[y_eq_d,expr]).proof()
def deduce_equality(self, equality, *, eq_via_elem_eq_thm=None, **defaults_config): from proveit import ExprRange from proveit import a, b, i from proveit.logic import Equals from proveit.core_expr_types.tuples import tuple_eq_via_elem_eq from proveit.relation import TransRelUpdater if not isinstance(equality, Equals): raise ValueError("The 'equality' should be an Equals expression") if equality.lhs != self: raise ValueError("The left side of 'equality' should be 'self'") from proveit.numbers import num, one # Handle the special counting cases. For example, # (1, 2, 3, 4) = (1, ..., 4) _n = len(self.entries) if all(self[_k] == num(_k + 1) for _k in range(_n)): if (isinstance(equality.rhs, ExprTuple) and equality.rhs.num_entries() == 1 and isinstance(equality.rhs[0], ExprRange)): expr_range = equality.rhs[0] if (expr_range.true_start_index == one and expr_range.true_end_index == num(_n)): if len(self.entries) >= 10: raise NotImplementedError("counting range equality " "not implemented for more " "then 10 elements") import proveit.numbers.numerals.decimals equiv_thm = proveit.numbers.numerals.decimals\ .__getattr__('count_to_%d_range' % _n) return equiv_thm lhs, rhs = equality.lhs, equality.rhs if (lhs.num_entries() == rhs.num_entries() == 1 and isinstance(lhs[0], ExprRange) and isinstance(rhs[0], ExprRange)): # Prove the equality of two ExprRanges. r_range = rhs[0] expr = lhs if expr[0].is_decreasing(): # We could handle different styles later, but # let's be consistent with increasing order for now # to make this easier to implement. expr = expr.inner_expr()[0].with_increasing_order() eq = TransRelUpdater(expr) if expr[0].true_start_index != r_range.true_start_index: # Shift indices so they have the same start. expr = eq.update(expr[0].shift_equivalence( new_start=r_range.true_start_index)) if expr[0].lambda_map != r_range.lambda_map: # Change the lambda map. expr = eq.update(expr[0].range_fn_transformation( r_range.lambda_map)) if expr[0].true_end_index != r_range.true_end_index: # Make the end indices be the same: end_eq = Equals(expr[0].true_end_index, r_range.true_end_index).prove() expr = eq.update(end_eq.substitution( expr.inner_expr()[0].true_end_index)) return eq.relation # Try tuple_eq_via_elem_eq as the last resort. _i = lhs.num_elements() _a = lhs _b = rhs if eq_via_elem_eq_thm is None: eq_via_elem_eq_thm = tuple_eq_via_elem_eq return eq_via_elem_eq_thm.instantiate({i:_i, a:_a, b:_b})