def __init__(self, value, condition_or_conditions): ''' Create a Conditional with the given particular value and the given condition. If multiple conditions are provided, these will be wrapped in a conjunction internally. However, if the 'condition_delimiter' style is set to 'comma', the conditions will be displayed in a comma delimited fashion if it is within a conjunction. ''' from proveit._core_.expression.composite import \ single_or_composite_expression, Composite, ExprTuple, ExprRange value = single_or_composite_expression(value) assert (isinstance(value, Expression) and not isinstance(value, ExprRange)) condition_or_conditions = \ single_or_composite_expression(condition_or_conditions) if isinstance(condition_or_conditions, ExprTuple): if is_single(condition_or_conditions): condition = condition_or_conditions[0] else: # Must wrap a tuple of conditions in a conjunction. from proveit.logic import And condition = And(*condition_or_conditions.entries) else: condition = condition_or_conditions assert (isinstance(condition, Expression) and not isinstance(condition, Composite)) Expression.__init__(self, ['Conditional'], (value, condition)) self.value = value self.condition = condition
def __init__(self, var, index_or_indices, *, styles=None): ''' Initialize an IndexedVar to represent the given 'var' being indexed via 'index_or_indices'. The 'var' must be a Variable. ''' from proveit._core_.expression.composite import composite_expression if not isinstance(var, Variable): raise TypeError("'var' being indexed should be a Variable " "or IndexedVar itself; got %s" % str(var)) self.indices = composite_expression(index_or_indices) if is_single(self.indices): # has a single index self.index = self.indices[0] self.index_or_indices = self.index else: self.index_or_indices = self.indices Function.__init__(self, var, self.index_or_indices, styles=styles) self.var = var
def auto_reduction(self, assumptions=USE_DEFAULTS): ''' Automatically reduce a conditional with a TRUE condition or with a condition that is a conjunction of two conjunctions, merging them into one. This latter reduction is useful when merging conditions from two sources. For example, showing\ that \forall_{x | A, B} \forall_{y | C, D} P(x, y) = \forall_{x, y | A, B, C, D} P(x, y) would make use of this reduction. ''' from proveit import a, m, n, Q, R from proveit.logic import And, TRUE if self.condition == TRUE: from proveit.core_expr_types.conditionals import \ true_condition_reduction return true_condition_reduction.instantiate({a: self.value}) elif isinstance(self.condition, And): from proveit.core_expr_types.conditionals import \ (singular_conjunction_condition_reduction, condition_merger_reduction, condition_append_reduction, condition_prepend_reduction, condition_with_true_on_left_reduction, condition_with_true_on_right_reduction) conditions = self.condition.operands if is_single(conditions): with defaults.disabled_auto_reduction_types as disabled_types: # Don't auto-reduce 'And' in this process disabled_types.discard(And) return singular_conjunction_condition_reduction \ .instantiate({a: self.value, Q: conditions[0]}) elif (conditions.num_entries() == 2 and isinstance(conditions[0], And)): _Q = conditions[0].operands _m = _Q.num_elements(assumptions) return condition_append_reduction.instantiate( { a: self.value, m: _m, Q: _Q, R: conditions[1] }, assumptions=assumptions) elif (conditions.num_entries() == 2 and isinstance(conditions[1], And)): _R = conditions[1].operands _n = _R.num_elements(assumptions) return condition_prepend_reduction.instantiate( { a: self.value, n: _n, Q: conditions[0], R: _R }, assumptions=assumptions) elif (conditions.num_entries() == 2 and all(isinstance(cond, And) for cond in conditions)): _Q = conditions[0].operands _R = conditions[1].operands _m = _Q.num_elements(assumptions) _n = _R.num_elements(assumptions) _a = self.value return condition_merger_reduction.instantiate( { m: _m, n: _n, a: _a, Q: _Q, R: _R }, assumptions=assumptions) elif (conditions.num_entries() == 2 and any(isinstance(cond, And) for cond in conditions) and any(cond == TRUE for cond in conditions)): if conditions[0] == TRUE: thm = condition_with_true_on_left_reduction _Q = conditions[1].operands else: assert conditions[1] == TRUE thm = condition_with_true_on_right_reduction _Q = conditions[0].operands _m = _Q.num_elements(assumptions) _a = self.value return thm.instantiate({ m: _m, a: _a, Q: _Q }, assumptions=assumptions)
def shallow_simplification(self, *, must_evaluate=False, **defaults_config): ''' Handles various Conditional reductions: {a if T. = a {{a if Q. if Q. = {a if Q. {a if [⋀](Q). = {a if Q. {a if a ⋀ b, c ⋀ d. = {a if a ⋀ b ⋀ c ⋀ d. etc. ''' from proveit import a, m, n, Q, R from proveit.logic import And, TRUE, Equals, is_irreducible_value if self.condition == TRUE: from proveit.core_expr_types.conditionals import \ true_condition_reduction return true_condition_reduction.instantiate({a: self.value}) elif self.condition.proven(): return self.satisfied_condition_reduction() elif self.condition.disproven(): return self.dissatisfied_condition_reduction() elif (isinstance(self.value, Conditional) and self.condition == self.value.condition): from proveit.core_expr_types.conditionals import \ redundant_condition_reduction return redundant_condition_reduction.instantiate({ a: self.value.value, Q: self.condition }) elif isinstance(self.condition, And): from proveit.core_expr_types.conditionals import \ (singular_conjunction_condition_reduction, condition_merger_reduction, condition_append_reduction, condition_prepend_reduction, true_condition_elimination, condition_with_true_on_left_reduction, condition_with_true_on_right_reduction) conditions = self.condition.operands if is_single(conditions): return singular_conjunction_condition_reduction \ .instantiate({a: self.value, Q: conditions[0]}) elif (conditions.is_double() and all(isinstance(cond, And) for cond in conditions)): _Q = conditions[0].operands _R = conditions[1].operands _m = _Q.num_elements() _n = _R.num_elements() _a = self.value return condition_merger_reduction.instantiate({ m: _m, n: _n, a: _a, Q: _Q, R: _R }) elif (conditions.num_entries() == 2 and any(isinstance(cond, And) for cond in conditions) and any(cond == TRUE for cond in conditions)): if conditions[0] == TRUE: thm = condition_with_true_on_left_reduction _Q = conditions[1].operands else: assert conditions[1] == TRUE thm = condition_with_true_on_right_reduction _Q = conditions[0].operands _m = _Q.num_elements() _a = self.value return thm.instantiate({m: _m, a: _a, Q: _Q}) elif (conditions.is_double() and isinstance(conditions[0], And)): _Q = conditions[0].operands _m = _Q.num_elements() return condition_append_reduction.instantiate({ a: self.value, m: _m, Q: _Q, R: conditions[1] }) elif (conditions.is_double() and isinstance(conditions[1], And)): _R = conditions[1].operands _n = _R.num_elements() return condition_prepend_reduction.instantiate({ a: self.value, n: _n, Q: conditions[0], R: _R }) elif any(cond == TRUE for cond in conditions): idx = conditions.index(TRUE) _Q = conditions[:idx] _R = conditions[idx + 1:] _m = _Q.num_elements() _n = _R.num_elements() return true_condition_elimination.instantiate({ a: self.value, Q: _Q, R: _R, m: _m, n: _n }) elif must_evaluate: # The only way we can equate a Conditional to an # irreducible is if we prove the condition to be true. self.condition.prove() return self.evaluation() # Use trivial self-reflection if there is no other # simplification to do. return Equals(self, self).prove()