示例#1
0
def total_ordering(*relations):
    '''
    Return a conjunction of relations in the total ordering style.
    For example, "a > b >= c = d > e" is a total ordering style for
    "(a > b) and (b >= c) and (c = d) and (d > e)".
    '''
    from proveit.logic import And
    conjunction = And(*relations)
    conjunction = conjunction.with_total_ordering_style()
    if conjunction.operands.is_single():
        # A single relation is a trivial total ordering.
        return conjunction.operands[0]
    return conjunction
示例#2
0
    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
示例#3
0
    def _equality_replaced_sub_exprs(self, recursion_fn, *, requirements,
                                     stored_replacements):
        '''
        Helper for Conditional._auto_simplified_sub_exprs and
        Expression._manual_equality_replaced.  The 'recursion_fn'
        allows this to satisfy both roles.
        '''
        from proveit.logic import And
        # Add the 'condition' as an assumption for the 'value' scope.
        # If there are multiple conditions in a conjunction, add them
        # as assumptions one by one and allow them to be used for
        # subsequent conditions.
        if isinstance(self.condition, And):
            conditions = self.condition.operands.entries
        else:
            conditions = [self.condition]

        # For each condition, we'll assume the previous substituted
        # conditions.
        subbed_conds = []
        prev_assumptions = defaults.assumptions
        inner_stored_repls = stored_replacements
        for _k, cond in enumerate(conditions):
            inner_assumptions = (defaults.assumptions + tuple(subbed_conds))
            with defaults.temporary() as temp_defaults:
                temp_defaults.assumptions = inner_assumptions
                if defaults.assumptions != prev_assumptions:
                    # Since the assumptions have changed, we can no
                    # longer use the stored_replacements from before.
                    inner_stored_repls = dict()
                prev_assumptions = defaults.assumptions
                subbed_conds.append(
                    recursion_fn(cond,
                                 requirements=requirements,
                                 stored_replacements=inner_stored_repls))

        # For the value, we'll assume all of the substituted conditions.
        inner_assumptions = (defaults.assumptions + tuple(subbed_conds))
        with defaults.temporary() as temp_defaults:
            temp_defaults.assumptions = inner_assumptions
            if defaults.assumptions != prev_assumptions:
                # Since the assumptions have changed, we can no longer
                # use the stored_replacements from before.
                inner_stored_repls = dict()
            subbed_val = recursion_fn(self.value,
                                      requirements=requirements,
                                      stored_replacements=inner_stored_repls)
        if len(subbed_conds) == 1:
            return (subbed_val, subbed_conds[0])
        else:
            subbed_condition = And(*subbed_conds)
            if subbed_condition != self.condition:
                # We can replace the altered subbed condition
                # conjunction; use the original assumptions and
                # stored replacements.
                subbed_condition = recursion_fn(
                    subbed_condition,
                    requirements=requirements,
                    stored_replacements=stored_replacements)
            return (subbed_val, subbed_condition)
示例#4
0
 def effectiveCondition(self):
     '''
     Return the effective 'condition' of the OperationOverInstances.
     If there is no 'condition', return And operating on zero
     operands.
     '''
     if hasattr(self, 'condition'):
         return self.condition
     else:
         from proveit.logic import And
         return And()
示例#5
0
 def negationSideEffects(self, knownTruth):
     '''
     Side-effect derivations to attempt automatically for Not(A or B or .. or .. Z).
     '''
     from proveit.logic import Not, And
     yield self.deriveInBool  # A or B or .. or .. Z in Booleans
     if len(self.operands) == 2:  # Not(A or B)
         yield self.deduceNotLeftIfNeither  # Not(A)
         yield self.deduceNotRightIfNeither  # Not(B)
     # implemented by JML on 7/2/19
     # If all of the operands are negated call the conjunction form of DeMorgan's
     if all(isinstance(operand, Not) for operand in self.operands):
         demorganAnd = And(*[operand.operand for operand in self.operands])
         yield demorganAnd.concludeViaDemorgans
示例#6
0
def total_ordering(*relations, prove=False):
    '''
    Return a conjunction of relations in the total ordering style.
    For example, "a > b >= c = d > e" is a total ordering style for
    "(a > b) and (b >= c) and (c = d) and (d > e)".  If there is a
    single relation, just return the relation.  If 'prove' is True,
    return a proven Judgment.
    '''
    from proveit import ExprRange
    from proveit.logic import And
    if len(relations) == 1 and not isinstance(relations[0], ExprRange):
        # Return a trivial, singular relation.
        relation = relations[0]
        if prove: relation = relation.prove()
        return relation
    # Return a conjunction with the proper style.
    conjunction = And(*relations)
    conjunction = conjunction.with_total_ordering_style()
    if prove:
        # Prove via composition.
        # Allow automation to prove the length requirement.
        return conjunction.conclude_via_composition(automation=True)
    return conjunction
示例#7
0
 def negation_side_effects(self, judgment):
     '''
     Side-effect derivations to attempt automatically for Not(A or B or .. or .. Z).
     '''
     from proveit.logic import Not, And
     if self.operands.num_entries() == 0:
         return  # No side-effects needed for [Or]()
     yield self.derive_in_bool  # A or B or .. or .. Z in Boolean
     if self.operands.is_double():  # Not(A or B)
         yield self.deduce_not_left_if_neither  # Not(A)
         yield self.deduce_not_right_if_neither  # Not(B)
     # implemented by JML on 7/2/19
     # If all of the operands are negated call the conjunction form of
     # DeMorgan's
     if all(isinstance(operand, Not) for operand in self.operands):
         demorgan_and = And(*[operand.operand for operand in self.operands])
         yield demorgan_and.conclude_via_demorgans
示例#8
0
 def foldAsForall(self, forallStmt, assumptions=USE_DEFAULTS):
     '''
     Given forall_{A in Booleans} P(A), conclude and return it from 
     [P(TRUE) and P(FALSE)].
     '''
     from proveit.logic import Forall, And
     from ._theorems_ import foldForallOverBool, foldConditionedForallOverBool
     from ._common_ import Booleans
     assert (
         isinstance(forallStmt, Forall)
     ), "May only apply foldAsForall method of Booleans to a forall statement"
     assert (
         forallStmt.domain == Booleans
     ), "May only apply foldAsForall method of Booleans to a forall statement with the Booleans domain"
     if (len(forallStmt.conditions) > 1):
         if len(forallStmt.conditions) == 2:
             condition = forallStmt.conditions[1]
         else:
             condition = And(*forallStmt.conditions[1:])
         Qx = Operation(Q, forallStmt.instanceVar)
         _Qx = condition
         Px = Operation(P, forallStmt.instanceVar)
         _Px = forallStmt.instanceExpr
         _A = forallStmt.instanceVar
         return foldConditionedForallOverBool.instantiate(
             {
                 Qx: _Qx,
                 Px: _Px,
                 A: _A
             },
             num_forall_eliminations=1,
             assumptions=assumptions)
     else:
         # forall_{A in Booleans} P(A), assuming P(TRUE) and P(FALSE)
         Px = Operation(P, forallStmt.instanceVar)
         _Px = forallStmt.instanceExpr
         _A = forallStmt.instanceVar
         return foldForallOverBool.instantiate({
             Px: _Px,
             A: _A
         },
                                               num_forall_eliminations=1,
                                               assumptions=assumptions)
示例#9
0
 def fold_as_forall(self, forall_stmt, assumptions=USE_DEFAULTS):
     '''
     Given forall_{A in Boolean} P(A), conclude and return it from
     [P(TRUE) and P(FALSE)].
     '''
     from proveit.logic import Forall, And
     from . import fold_forall_over_bool, fold_conditioned_forall_over_bool
     from . import Boolean
     assert (
         isinstance(forall_stmt, Forall)
     ), "May only apply fold_as_forall method of Boolean to a forall statement"
     assert (
         forall_stmt.domain == Boolean
     ), "May only apply fold_as_forall method of Boolean to a forall statement with the Boolean domain"
     if forall_stmt.conditions.num_entries() > 1:
         if forall_stmt.conditions.is_double():
             condition = forall_stmt.conditions[1]
         else:
             condition = And(*forall_stmt.conditions[1:].entries)
         Qx = Operation(Q, forall_stmt.instance_var)
         _Qx = condition
         Px = Operation(P, forall_stmt.instance_var)
         _Px = forall_stmt.instance_expr
         _A = forall_stmt.instance_var
         return fold_conditioned_forall_over_bool.instantiate(
             {
                 Qx: _Qx,
                 Px: _Px,
                 A: _A
             },
             num_forall_eliminations=1,
             assumptions=assumptions)
     else:
         # forall_{A in Boolean} P(A), assuming P(TRUE) and P(FALSE)
         Px = Operation(P, forall_stmt.instance_param)
         _Px = forall_stmt.instance_expr
         _A = forall_stmt.instance_param
         return fold_forall_over_bool.instantiate({
             Px: _Px,
             A: _A
         },
                                                  num_forall_eliminations=1,
                                                  assumptions=assumptions)
示例#10
0
 def prove_by_cases(self, forall_stmt, **defaults_config):
     '''
     Given forall_{A in Boolean} P(A), conclude and return it from
     [P(TRUE) and P(FALSE)].
     '''
     from proveit.logic import Forall, And
     from . import forall_over_bool_by_cases, conditioned_forall_over_bool_by_cases
     from . import Boolean
     assert(isinstance(forall_stmt, Forall)), (
             "May only apply prove_by_cases method of Boolean to a "
             "forall statement")
     assert(forall_stmt.domain == Boolean), (
             "May only apply prove_by_cases method of Boolean "
             "to a forall statement with the Boolean domain")
     if forall_stmt.conditions.num_entries() > 1:
         if forall_stmt.conditions.is_double():
             condition = forall_stmt.conditions[1]
         else:
             condition = And(*forall_stmt.conditions[1:].entries)
         Qx = Function(Q, forall_stmt.instance_param)
         _Qx = condition
         Px = Function(P, forall_stmt.instance_param)
         _Px = forall_stmt.instance_expr
         _A = forall_stmt.instance_param
         # We may need to auto-simplify in order to flatten the
         # conditions (if there are multiple conditions beyond the
         # domain condition), but we must preserve the different
         # parts.
         preserved_exprs = {forall_stmt, forall_stmt.instance_expr}
         preserved_exprs.update(forall_stmt.conditions)    
         return conditioned_forall_over_bool_by_cases.instantiate(
                 {Qx: _Qx, Px: _Px, A: _A}, num_forall_eliminations=1, 
                 preserved_exprs=preserved_exprs, auto_simplify=True)
     else:
         # forall_{A in Boolean} P(A), assuming P(TRUE) and P(FALSE)
         Px = Function(P, forall_stmt.instance_param)
         _Px = forall_stmt.instance_expr
         _A = forall_stmt.instance_param
         return forall_over_bool_by_cases.instantiate(
             {Px: _Px, A: _A}, num_forall_eliminations=1,
             preserve_expr=forall_stmt)
示例#11
0
 def substitute_domain(self, superset, **defaults_config):
     '''
     Substitute the domain with a superset.
     From [exists_{x in A| Q(x)} P(x)], derive and return 
     [exists_{x in B| Q(x)} P(x)]
     given A subseteq B.
     '''
     from proveit.logic import And
     from . import exists_in_superset
     _x = self.instance_params
     _P = Lambda(_x, self.instance_expr)
     if self.conditions.num_entries() == 1:
         _Q = Lambda(_x, self.condition)
     else:
         _Q = Lambda(_x, And(self.conditions[1:]))
     _impl = exists_in_superset.instantiate({
         P: _P,
         Q: _Q,
         A: self.domain,
         B: superset,
         x: _x,
         y: _x
     })
     return _impl.derive_consequent()
示例#12
0
def deduce_number_set(expr, **defaults_config):
    '''
    Prove that 'expr' is an Expression that represents a number
    in a standard number set that is as restrictive as we can
    readily know.
    '''
    from proveit.logic import And, InSet, Equals, NotEquals
    from proveit.numbers import Less, LessEq, zero

    # Find the first (most restrictive) number set that
    # contains 'expr' or something equal to it.

    for number_set in sorted_number_sets:
        membership = None
        for eq_expr in Equals.yield_known_equal_expressions(expr):
            if isinstance(eq_expr, ExprRange):
                membership = And(
                    ExprRange(eq_expr.parameter,
                              InSet(eq_expr.body, number_set),
                              eq_expr.true_start_index,
                              eq_expr.true_end_index,
                              styles=eq_expr.get_styles()))
            else:
                membership = InSet(eq_expr, number_set)
            if membership.proven():
                break  # found a known number set membership
            else:
                membership = None
        if membership is not None:
            membership = InSet(expr, number_set).prove()
            break

    if hasattr(expr, 'deduce_number_set'):
        # Use 'deduce_number_set' method.
        try:
            deduced_membership = expr.deduce_number_set()
        except (UnsatisfiedPrerequisites, ProofFailure):
            deduced_membership = None
        if deduced_membership is not None:
            assert isinstance(deduced_membership, Judgment)
            if not isinstance(deduced_membership.expr, InSet):
                raise TypeError("'deduce_number_set' expected to prove an "
                                "InSet type expression")
            if deduced_membership.expr.element != expr:
                raise TypeError("'deduce_number_set' was expected to prove "
                                "that %s is in some number set" % expr)
            # See if this deduced number set is more restrictive than
            # what we had surmised already.
            deduced_number_set = deduced_membership.domain
            if membership is None:
                membership = deduced_membership
                number_set = deduced_number_set
            elif (deduced_number_set != number_set
                  and number_set.includes(deduced_number_set)):
                number_set = deduced_number_set
                membership = deduced_membership

    if membership is None:
        from proveit import defaults
        raise UnsatisfiedPrerequisites(
            "Unable to prove any number membership for %s" % expr)

    # Already proven to be in some number set,
    # Let's see if we can restrict it further.
    if Less(zero, expr).proven():  # positive
        number_set = pos_number_set.get(number_set, None)
    elif Less(expr, zero).proven():  # negative
        number_set = neg_number_set.get(number_set, None)
    elif LessEq(zero, expr).proven():  # non-negative
        number_set = nonneg_number_set.get(number_set, None)
    elif LessEq(expr, zero).proven():  # non-positive
        number_set = nonpos_number_set.get(number_set, None)
    elif NotEquals(expr, zero).proven():
        number_set = nonzero_number_set.get(number_set, None)
    if number_set is None:
        # Just use what we have already proven.
        return membership.prove()
    return InSet(expr, number_set).prove()
示例#13
0
    def eliminate(skolem_constants, judgment, **defaults_config):
        '''
        For the provided judgment of the form S |– alpha and the tuple
        of Skolem constants skolem_constants that had been specified
        earlier using the Exists.choose(), derive and return a new
        judgment S' |– alpha where all assumptions in S involving only
        the given skolem_constants are now eliminated.
        This process will only work if the provided skolem_constants
        exactly match a set of Skolem constants used earlier in an
        Exists.choose() method to produce the Skolem constant-based
        subset of assumptions you wish to eliminate from S.
        '''
        from proveit import Lambda
        from proveit import n, P, Q, alpha
        from proveit.logic import And
        from proveit.core_expr_types import (x_1_to_n, y_1_to_n)
        from proveit.logic.booleans.quantification.existence import (
            skolem_elim)
        if skolem_constants not in Exists.skolem_consts_to_existential:
            raise KeyError("In calling Exists.eliminate(), the Skolem "
                           "constants provided were: {}, but you can only "
                           "eliminate Skolem constants that were chosen "
                           "earlier when using Exists.choose() and the "
                           "Skolem constants to be eliminated must appear "
                           "exactly as specified in the original "
                           "Exists.choose() method.".format(skolem_constants))
        existential = Exists.skolem_consts_to_existential[skolem_constants]
        skolem_assumptions = set(
            existential.choose(*skolem_constants, print_message=False))
        with defaults.temporary() as temp_defaults:
            temp_defaults.assumptions = (
                assumption for assumption in defaults.assumptions
                if assumption not in skolem_assumptions)

            _P = Lambda(existential.instance_params, existential.instance_expr)
            if hasattr(existential, 'condition'):
                _Q = Lambda(existential.instance_params, existential.condition)
            else:
                # There is no condition but we still need to provide
                # something for _Q so we provide an empty conjunction,
                # And().
                _Q = Lambda(existential.instance_params, And())
            _alpha = judgment
            _n = existential.instance_params.num_elements()
            x_1_to__n = ExprTuple(x_1_to_n.basic_replaced({n: _n}))
            y_1_to__n = ExprTuple(y_1_to_n.basic_replaced({n: _n}))

            # express the judgment as an implication to match details of
            # the skolem_elim theorem being instantiated further below
            P_implies_alpha = _alpha.as_implication(hypothesis=_P.apply(
                *skolem_constants))
            # the generalization to further match theorem details
            # can be handled through automation
            # P_implies_alpha.generalize(
            #         skolem_constants,
            #         conditions=[_Q.apply(*skolem_constants)])

            return skolem_elim.instantiate(
                {
                    n: _n,
                    P: _P,
                    Q: _Q,
                    alpha: _alpha,
                    x_1_to__n: skolem_constants,
                    y_1_to__n: existential.instance_params
                },
                preserve_all=True).derive_consequent()
示例#14
0
absIsNonNeg = Forall(a, GreaterThanEquals(Abs(a), zero), domain=Complexes)
absIsNonNeg

absNotEqZero = Forall([a],
                      NotEquals(Abs(a), zero),
                      domain=Complexes,
                      conditions=[NotEquals(a, zero)])
absNotEqZero

absElim = Forall(x, Equals(Abs(x), x), domain=RealsPos)
absElim

absIneq = Forall((x, y),
                 Iff(LessThanEquals(Abs(x), y),
                     And(LessThanEquals(Neg(y), x), LessThanEquals(x, y))),
                 domain=Reals,
                 conditions=[GreaterThanEquals(y, zero)])
absIneq

triangleInequality = Forall([a, b],
                            LessThanEquals(Abs(Add(a, b)), Add(Abs(a),
                                                               Abs(b))),
                            domain=Complexes)
triangleInequality

absProd = Forall(xEtc,
                 Equals(Abs(Mult(xEtc)), Mult(Etcetera(Abs(xMulti)))),
                 domain=Complexes)
absProd
示例#15
0
from proveit.logic import Forall, Equals, And, InSet
from proveit.number import Floor, Sub, IntervalCO, Integers, Reals
from proveit.common import x
from proveit.number.common import zero, one
from proveit import beginAxioms, endAxioms

beginAxioms(locals())

floorDef = Forall(x,
                  And(InSet(Floor(x), Integers),
                      InSet(Sub(x, Floor(x)), IntervalCO(zero, one))),
                  domain=Reals)
floorDef

endAxioms(locals(), __package__)
示例#16
0
true_eq_false_eval = Equals(Equals(TRUE, FALSE), FALSE)

false_eq_true_eval = Equals(Equals(FALSE, TRUE), FALSE)

true_conclusion = Forall(A, Implies(A, TRUE))

in_bool_equiv = Forall(
    A, Equals(in_bool(A), Or(Equals(A, TRUE), Equals(A, FALSE))))

true_is_bool = in_bool(TRUE)

false_is_bool = in_bool(FALSE)

unfold_forall_over_bool = Forall(
    P, Implies(Forall(A, PofA, domain=Boolean), And(PofTrue, PofFalse)))

in_bool_if_true = Forall(A, in_bool(A), conditions=[A])

in_bool_if_false = Forall(A, in_bool(A), conditions=[Not(A)])

# This weak form requires B to be a Boolean
by_cases_weak = Forall((A, B),
                       B,
                       domain=Boolean,
                       conditions=[Implies(A, B),
                                   Implies(Not(A), B)])

# This is a stronger form that does not require B to be a Boolean
by_cases = Forall(A,
                  Forall(B, B, conditions=[Implies(A, B),
示例#17
0
    def conclude(self, **defaults_config):
        '''
        Try to automatically conclude this disjunction.  If any of its
        operands have pre-existing proofs, it will be proven via the
        or_if_any theorem.  Otherwise, a reduction proof will be
        attempted (evaluating the operands).
        '''
        from proveit.logic import And
        from . import true_or_true, true_or_false, false_or_true
        if self in {true_or_true.expr, true_or_false.expr, false_or_true.expr}:
            # should be proven via one of the imported theorems as a
            # simple special case
            return self.prove()
        # Prove that the disjunction is true by proving that ANY of its
        # operands is true.   In the first attempt, don't use automation
        # to prove any of the operands so that  we don't waste time
        # trying to prove operands when we already know one to be true.
        use_automation_possibilities = ([False, True]
                                        if defaults.automation else [False])

        if self.operands.contains_range():
            # There are ExprRange operands.
            if self.operands.num_entries() == 1:
                # Just a single ExprRange.
                if And(self.operands.entries[0]).proven():
                    # Trivally, if all of the operands are
                    # True then any of them are, as long as
                    # there is at list one (note,
                    # Or() = FALSE, so we shouldn't try to
                    # conclude Or() anyway).
                    return self.conclude_any_via_all()
                # Use DeMorgan's law.
                return self.conclude_via_demorgans()
            # Group each ExprRange operand, call conclude_negation,
            # then disassociate the ExprRange operands.
            return prove_via_grouping_ranges(
                self, lambda expr, **kwargs: expr.conclude(**kwargs))

        for use_automation_for_operand in use_automation_possibilities:
            proven_operand_indices = []
            for _k, operand in enumerate(self.operands):
                try:
                    operand.prove(automation=use_automation_for_operand)
                    proven_operand_indices.append(_k)
                    # possible way to prove it:
                    self.conclude_via_example(operand)
                except ProofFailure:
                    pass
            if self.operands.is_double() and len(proven_operand_indices) > 0:
                # One or both of the two operands were known to be true
                # (without automation).   Try a possibly simpler proof
                # than conclude_via_example.
                try:
                    if len(proven_operand_indices) == 2:
                        return self.conclude_via_both()
                    elif proven_operand_indices[0] == 0:
                        return self.conclude_via_only_left()
                    else:
                        return self.conclude_via_only_right()
                except BaseException:
                    pass
            if len(proven_operand_indices) > 0:
                try:
                    # proven using conclude_via_example above
                    # (unless or_if[Any,Left,Right] was not a usable
                    # theorem, in which case this will fail and we
                    # can simply try the default below)
                    return self.prove(automation=False)
                except UnusableProof:
                    # or_if[Any,Left,Right] must not have been a usable
                    # theorem; use the default below.
                    break

        raise ProofFailure(
            self, defaults.assumptions,
            "Or.conclude() has failed to find a proof for the "
            "disjunction: ({})".format(self))
示例#18
0
from proveit.common import n, xMulti, xEtc, x, y, S
from common import zero, one, two
from proveit import beginAxioms, endAxioms

beginAxioms(locals())

# Define the set of Naturals as, essentially, the minimum set that contains zero and all of its successors;
# that is, n is in Naturals iff n is in all sets that contain zero and all successors.
naturalsDef = Forall(
    n,
    Equals(
        InSet(n, Naturals),
        Forall(
            S,
            Implies(
                And(InSet(zero, S), Forall(x, InSet(Add(x, one), S),
                                           domain=S)), InSet(n, S)))))

# Define the length of an ExpressionList inductively.
exprListLengthDef = And(
    Equals(Len(), zero),
    Forall((xMulti, y), Equals(Len(xEtc, y), Add(Len(xEtc), one))))

naturalsPosDef = Forall(n,
                        Iff(InSet(n, NaturalsPos), GreaterThanEquals(n, one)),
                        domain=Naturals)
naturalsPosDef

integersDef = Equals(Integers,
                     Union(Naturals, SetOfAll(n, Neg(n), domain=Naturals)))

endAxioms(locals(), __package__)
示例#19
0
from .common import zero, one, two
from proveit import begin_axioms, end_axioms

begin_axioms(locals())

# Define the set of Natural as, essentially, the minimum set that contains zero and all of its successors;
# that is, n is in Natural iff n is in all sets that contain zero and all
# successors.
naturals_def = Forall(
    n,
    Equals(
        InSet(n, Natural),
        Forall(
            S,
            Implies(
                And(InSet(zero, S), Forall(x, InSet(Add(x, one), S),
                                           domain=S)), InSet(n, S)))))

# Define the length of an ExpressionList inductively.
expr_list_length_def = And(
    Equals(Len(), zero),
    Forall((x_multi, y), Equals(Len(x_etc, y), Add(Len(x_etc), one))))

naturals_pos_def = Forall(n,
                          Iff(InSet(n, NaturalPos), GreaterThanEquals(n, one)),
                          domain=Natural)
naturals_pos_def

integers_def = Equals(Integer,
                      Union(Natural, SetOfAll(n, Neg(n), domain=Natural)))

end_axioms(locals(), __package__)
示例#20
0
from proveit.logic import Forall, InSet, NotInSet, NotEquals, And, Implies, Equals, Booleans
from proveit.number import Integers, Naturals, NaturalsPos, Interval, Reals, RealsPos, Complexes
from proveit.number import Add, GreaterThan, GreaterThanEquals, LessThan, LessThanEquals
from proveit.number import Len
from proveit.common import a, b, n, m, x, y, P, S, xMulti, xEtc, PxEtc
from proveit.number import zero, one, two, three, four, five, six, seven, eight, nine
from proveit.number.common import Pzero, Pm, P_mAddOne, Pn
from proveit import beginTheorems, endTheorems

beginTheorems(locals())

zeroInNats = InSet(zero, Naturals)

successiveNats = Forall(n, InSet(Add(n, one), Naturals), domain=Naturals)

inductionLemma = Forall(n, Forall(S, Implies(And(InSet(zero, S), Forall(x, InSet(Add(x,one), S), domain=S)), InSet(n, S))), domain=Naturals)

induction = Forall(P, Implies(And(Pzero, Forall(m, P_mAddOne, domain=Naturals, conditions=[Pm])), Forall(n, Pn, Naturals)))

zeroLenExprList = Equals(Len(), zero)

multiVarInduction = Forall(P, Implies(Forall((xMulti, y), Implies(PxEtc, Operation(P, [xEtc, y]))), Forall(xMulti, PxEtc)))

inIntsIsBool = Forall(a, InSet(InSet(a, Integers), Booleans))
inIntsIsBool

notInIntsIsBool = Forall(a, InSet(NotInSet(a, Integers), Booleans))
notInIntsIsBool

intsInReals = Forall(a, InSet(a, Reals), domain=Integers)
intsInReals
示例#21
0
        NotEquals(
            a,
            zero)])
abs_not_eq_zero

# transferred by wdc 3/11/2020
abs_elim = Forall(x, Equals(Abs(x), x),
                  domain=RealPos)
abs_elim

# transferred by wdc 3/11/2020
abs_ineq = Forall(
    (x, y), Iff(
        LessThanEquals(
            Abs(x), y), And(
                LessThanEquals(
                    Neg(y), x), LessThanEquals(
                        x, y))), domain=Real, conditions=[
                            GreaterThanEquals(
                                y, zero)])
abs_ineq

# transferred by wdc 3/11/2020
triangle_inequality = Forall([a, b], LessThanEquals(
    Abs(Add(a, b)), Add(Abs(a), Abs(b))), domain=Complex)
triangle_inequality

# transferred by wdc 3/11/2020
abs_prod = Forall(x_etc,
                  Equals(Abs(Mult(x_etc)),
                         Mult(Etcetera(Abs(x_multi)))),
                  domain=Complex)
示例#22
0
def unbundle(expr,
             unbundle_thm,
             num_param_entries=(1, ),
             *,
             assumptions=USE_DEFAULTS):
    '''
    Given a nested OperationOverInstances, derive or equate an
    equivalent form in which the parameter entries are split in
    number according to 'num_param_entries'.  Use the given theorem
    specific to the particular OperationOverInstances.

    For example,
        \forall_{x, y, z | Q(x, y), R(z)} P(x, y, z)
    can become
        \forall_{x, y | Q(x, y)} \forall_{z | R(z)} P(x, y, z)
    via bundle with num_param_entries=(2, 1) or
    num_param_entries=(2,) -- the last number can be implied
    by the remaining number of parameters.

    For example of the form of the theorem required, see
    proveit.logic.boolean.quantification.unbundling or
    proveit.logic.boolean.quantification.bundling_equality.
    '''
    from proveit.relation import TransRelUpdater
    from proveit.logic import Implies, Equals, And
    # Make a TransRelUpdater only if the bundle_thm yield an
    # equation, in which case we'll want the result to be an equation.
    eq = None
    unbundled = expr
    net_indicated_param_entries = sum(num_param_entries)
    num_actual_param_entries = len(expr.instanceParams)
    for n in num_param_entries:
        if not isinstance(n, int) or n <= 0:
            raise ValueError(
                "Each of 'num_param_entries', must be an "
                "integer greater than 0.  %s fails this requirement." %
                (num_param_entries))
    if net_indicated_param_entries > num_actual_param_entries:
        raise ValueError(
            "Sum of 'num_param_entries', %s=%d should not "
            "be greater than the number of parameter entries "
            "of %s for unbundling." %
            (num_param_entries, net_indicated_param_entries, expr))
    if net_indicated_param_entries < num_actual_param_entries:
        diff = num_actual_param_entries - net_indicated_param_entries
        num_param_entries = list(num_param_entries) + [diff]
    else:
        num_param_entries = list(num_param_entries)
    while len(num_param_entries) > 1:
        n_last_entries = num_param_entries.pop(-1)
        first_params = ExprTuple(*unbundled.instanceParams[:-n_last_entries])
        first_param_vars = {getParamVar(param) for param in first_params}
        remaining_params = \
            ExprTuple(*unbundled.instanceParams[-n_last_entries:])
        _m = first_params.length()
        _n = remaining_params.length()
        _P = unbundled.instanceExpr
        # Split up the conditions between the outer
        # OperationOverInstances and inner OperationOverInstances
        condition = unbundled.effectiveCondition()
        if isinstance(condition, And):
            _nQ = 0
            for cond in condition.operands:
                cond_vars = free_vars(cond, err_inclusively=True)
                if first_param_vars.isdisjoint(cond_vars): break
                _nQ += 1
            if _nQ == 0:
                _Q = And()
            elif _nQ == 1:
                _Q = condition.operands[0]
            else:
                _Q = And(*condition.operands[:_nQ])
            _nR = len(condition.operands) - _nQ
            if _nR == 0:
                _R = And()
            elif _nR == 1:
                _R = condition.operands[-1]
            else:
                _R = And(*condition.operands[_nQ:])
        elif first_param_vars.isdisjoint(
                free_vars(condition, err_inclusively=True)):
            _Q = condition
            _R = And()
        else:
            _Q = And()
            _R = condition
        m, n = unbundle_thm.instanceVars
        P, Q, R = unbundle_thm.instanceExpr.instanceVars
        correspondence = unbundle_thm.instanceExpr.instanceExpr
        if isinstance(correspondence, Implies):
            if (not isinstance(correspondence.antecedent,
                               OperationOverInstances)
                    or not len(correspondence.antecedent.instanceParams) == 2):
                raise ValueError("'unbundle_thm', %s, does not have the "
                                 "expected form with the bundled form as "
                                 "the antecedent of the implication, %s" %
                                 (unbundle_thm, correspondence))
            x_1_to_m, y_1_to_n = correspondence.antecedent.instanceParams
        elif isinstance(correspondence, Equals):
            if not isinstance(
                    correspondence.rhs, OperationOverInstances
                    or not len(correspondence.antecedent.instanceParams) == 2):
                raise ValueError("'unbundle_thm', %s, does not have the "
                                 "expected form with the bundled form on "
                                 "right of the an equality, %s" %
                                 (unbundle_thm, correspondence))
            x_1_to_m, y_1_to_n = correspondence.rhs.instanceParams
        else:
            raise ValueError("'unbundle_thm', %s, does not have the expected "
                             "form with an equality or implication  "
                             "correspondence, %s" %
                             (unbundle_thm, correspondence))

        Qx = Function(Q, first_params)
        Rxy = Function(R, unbundled.instanceParams)
        Pxy = Function(P, unbundled.instanceParams)
        x_1_to_m = x_1_to_m.replaced({m: _m})
        y_1_to_n = y_1_to_n.replaced({n: _n})
        instantiation = unbundle_thm.instantiate(
            {
                m: _m,
                n: _n,
                ExprTuple(x_1_to_m): first_params,
                ExprTuple(y_1_to_n): remaining_params,
                Pxy: _P,
                Qx: _Q,
                Rxy: _R
            },
            assumptions=assumptions)
        if isinstance(instantiation.expr, Implies):
            unbundled = instantiation.deriveConsequent()
        elif isinstance(instantiation.expr, Equals):
            if eq is None:
                eq = TransRelUpdater(unbundled)
            try:
                unbundled = eq.update(instantiation)
            except ValueError:
                raise ValueError(
                    "Instantiation of bundle_thm %s is %s but "
                    "should match %s on one side of the equation." %
                    (unbundle_thm, instantiation, unbundled))
        else:
            raise ValueError("Instantiation of bundle_thm %s is %s but "
                             "should be an Implies or Equals expression." %
                             (unbundle_thm, instantiation))
    if eq is None:
        # Return the unbundled result.
        return unbundled
    else:
        # Return the equality between the original expression and
        # the unbundled result.
        return eq.relation
示例#23
0
from proveit.numbers import zero, one, two, three, four, five, six, seven, eight, nine
from proveit.numbers.common import Pzero, Pm, P_mAddOne, Pn
from proveit import begin_theorems, end_theorems

begin_theorems(locals())

zero_in_nats = InSet(zero, Natural)

successive_nats = Forall(n, InSet(Add(n, one), Natural), domain=Natural)

induction_lemma = Forall(n,
                         Forall(
                             S,
                             Implies(
                                 And(
                                     InSet(zero, S),
                                     Forall(x, InSet(Add(x, one), S),
                                            domain=S)), InSet(n, S))),
                         domain=Natural)

induction = Forall(
    P,
    Implies(And(Pzero, Forall(m, P_mAddOne, domain=Natural, conditions=[Pm])),
            Forall(n, Pn, Natural)))

zero_len_expr_tuple = Equals(Len(), zero)

multi_var_induction = Forall(
    P,
    Implies(Forall((x_multi, y), Implies(Px_etc, Operation(P, [x_etc, y]))),
            Forall(x_multi, Px_etc)))
示例#24
0
    def deduce_equal_or_not(self, other_tuple, **defaults_config):
        '''
        Prove and return that this ExprTuple is either equal or
        not equal to other_tuple or raises an UnsatisfiedPrerequisites
        or NotImplementedError if we cannot readily prove either of
        these.
        '''
        from proveit import (ExprRange, safe_dummy_var,
                             UnsatisfiedPrerequisites)
        from proveit.logic import (
                And, Or, Equals, NotEquals, deduce_equal_or_not)
        if self == other_tuple:
            return Equals(self, other_tuple).conclude_via_reflexivity
        if not isinstance(other_tuple, ExprTuple):
            raise TypeError("Expecting 'other_tuple' to be an ExprTuple "
                            "not a %s"%other_tuple.__class__)
        _i = self.num_elements()
        _j = other_tuple.num_elements()
        size_relation = deduce_equal_or_not(_i, _j)
        if isinstance(size_relation.expr, NotEquals):
            # Not equal because the lengths are different.
            return self.not_equal(other_tuple)
        
        def raise_non_corresponding():
            raise NotImplementedError(
                    "ExprTuple.deduce_equal_or_not is only "
                    "implemented for the case when ExprRanges "
                    "match up: %s vs %s"%self, other_tuple)
            
        if self.num_entries() == other_tuple.num_entries():
            if self.num_entries()==1 and self.contains_range():
                if not other_tuple.contains_range():
                    # One ExprTuple has a range but the other doesn't.
                    # That case isn't handled.
                    raise_non_corresponding()
                lhs_range = self.entries[0]
                rhs_range = other_tuple.entries[0]
                start_index = lhs_range.start_index
                end_index = lhs_range.end_index
                if ((start_index != rhs_range.start_index) or
                        (end_index != rhs_range.end_index)):
                    # Indices must match for a proper correspondence.
                    raise_non_corresponding()
                if lhs_range.parameter != rhs_range.parameter:
                    # Use a safe common parameter.
                    param = safe_dummy_var(lhs_range.body, rhs_range.body)
                    lhs_range_body = lhs_range.body.basic_replaced(
                            {lhs_range.parameter: param})
                    rhs_range_body = rhs_range.body.basic_replaced(
                            {rhs_range.parameter: param})
                else:
                    param = lhs_range.parameter
                    lhs_range_body = lhs_range.body
                    rhs_range_body = rhs_range.body
                inner_assumptions = defaults.assumptions + (
                        lhs_range.parameter_condition(),)
                try:
                    body_relation = deduce_equal_or_not(
                            lhs_range_body, rhs_range_body,
                            assumptions=inner_assumptions)
                    if isinstance(body_relation, Equals):
                        # Every element is equal, so the ExprTuples 
                        # are equal.
                        return self.deduce_equality(
                                Equals(self, other_tuple))
                    else:
                        # Every element is not equal, so the ExprTuples 
                        # are not equal.
                        # This will enable "any" from "all".
                        And(ExprRange(
                                param, NotEquals(lhs_range_body,
                                                 rhs_range_body),
                                start_index, end_index)).prove()
                        return self.not_equal(other_tuple)
                except (NotImplementedError, UnsatisfiedPrerequisites):
                    pass
                if And(ExprRange(param, Equals(lhs_range_body, 
                                               rhs_range_body),
                                 start_index, end_index)).proven():
                    # Every element is equal, so the ExprTuples 
                    # are equal.
                    return self.deduce_equality(
                            Equals(self, other_tuple))
                elif Or(ExprRange(param, NotEquals(lhs_range_body,
                                                   rhs_range_body),
                        start_index, end_index)).proven():
                    # Some element pair is not equal, so the ExprTuples 
                    # are not equal.
                    return self.not_equal(other_tuple)
                raise UnsatisfiedPrerequisites(
                        "Could not determine whether %s = %s"
                        %(self, other_tuple))
            
            # Loop through each entry pair in correspondence and
            # see if we can readily prove whether or not they are
            # all equal.
            for idx, (_x, _y) in enumerate(
                    zip(self.entries, other_tuple.entries)):
                if isinstance(_x, ExprRange) != isinstance(_y, ExprRange):
                    raise_non_corresponding()
                if _x == _y:
                    # The expressions are the same, so we know they
                    # are equal.
                    continue
                if isinstance(_x, ExprRange):
                    # Wrap ExprRanges in ExprTuples and compare as
                    # single entry tuples.
                    _x = ExprTuple(_x)
                    _y = ExprTuple(_y)
                    _k = _x.num_elements()
                    _l = _y.num_elements()
                    size_relation = deduce_equal_or_not(_k, _l)
                    if isinstance(size_relation.expr, NotEquals):
                        # Not implemented when the ExprRanges don't
                        # correspond in size.
                        raise_non_corresponding()
                    relation = deduce_equal_or_not(_x, _y)
                else:
                    # Compare singular entries.
                    relation = deduce_equal_or_not(_x, _y)
                if isinstance(relation.expr, NotEquals):
                    # Aha! They are not equal.
                    return self.not_equal(other_tuple)
            # They are equal!
            return self.deduce_equality(Equals(self, other_tuple))

        raise NotImplementedError(
                    "ExprTuple.deduce_equal_or_not is not implemented "
                    "for ExprTuples that have a different number of "
                    "elements.")