import proveit
from proveit import defaults, free_vars, used_vars, ProofFailure
from proveit import a, b, c, n, x, y
from proveit.logic import Equals, InSet, NotEquals
from proveit.numbers import one, zero, two, three, four, five, six, Complex, Integer, NaturalPos
from proveit.numbers import Add, Divides, DividesProper, Exp, GCD, Mult
from proveit.numbers.divisibility import divides_def
from proveit.numbers.divisibility import divides_is_bool
%begin demonstrations
Divisibility of one number by another is a common concern throughout various fields of mathematics $\dots$ The notation $x\rvert y$, read as “x divides y,” indicates that $x$ is a factor of $y$, or $y$ is a multiple of $x$, and is often defined as meaning there exists some integer $k$ such that $y=kx$. As we'll see further below in the section on axioms, in Prove-It we define $x\rvert y$ as meaning that $\frac{y}{x} \in \mathbb{Z}$. This ``_demonstrations_`` notebook explores $x\rvert y$ expressions and related methods.
Expressions involving divisibility claims are easy to construct using the Divides() class. Here are some basic examples of such expressions:
# a simple divisibility claim
Divides(x, y)
# some other examples, some true, some false, some indeterminant
example_1, example_2, example_3, example_4, example_5 = (
Divides(two, four), Divides(x, x), Divides(a, Add(b, c)),
Divides(six, three), Divides(x, Mult(x,y)))
Consider ``example_5`` from above, $x\rvert(xy)$, which is true for all $x\ne 0$, and look at some of its attributes.
We can look at the construction of such an expression by calling expr_info() to see the tabular representation of the expression's underlying directed acyclic graph (DAG) representation:</font>
example_5.expr_info()
We can access the left-hand and right-hand sides of such expressions in terms of operands:
example_5.operands
example_5.operands[0]
example_5.operands[1]
We can access the “divides” operator itself:
example_5.operator
If and when needed, we can check for an expression being an instance of the Divides class:
isinstance(example_5, Divides)
We can also get a list of the variables and a separate list of the *free* variables in the expression (of course, in this expression, all the variables are also free variables):
used_vars(example_5)
free_vars(example_5)
Currently there is a single ``axiom`` for the divisibility theory, establishing the basic definition for $x\rvert y$ (see [divisibility axioms](./_axioms_.ipynb) page.) for updates).
# def of x|y
divides_def
Divisibility $x\rvert y$ involving non-zero integers $x$ and $y$ is often defined as $(x\rvert y) = \exists_{k\in\mathbb{Z}}[y = kx]$. The axiomatic definition shown above is essentially the same, implicitly disallowing $x=0$ by the nature of the fraction $\frac{y}{x}$, but also allowing $y=0$.
The `number/divisbility` theory has a handful of related theorems and conjectures established, with a number of other possibilities still open for development. Some illustrative examples of the theorems are shown below, and the remainder can be found in the [divisibility theorems notebook](./\_theorems\_.ipynb).
from proveit.numbers.divisibility import (
divides_is_bool, divides_transitivity, divides_reflexivity,
divides_anti_symmetry, euclids_lemma, divides_sum, non_zero_divides_zero)
# divisibility claims are Boolean
divides_is_bool
# divisbility is transitive
divides_transitivity
# divisbility is reflexive
divides_reflexivity
# divisbility manifests a form of antisymmetry
divides_anti_symmetry
# when dealing with integers, we can make some important claims
euclids_lemma
# divisibility across sums of divisible pieces
divides_sum
# everything (non-zero) divides zero
non_zero_divides_zero
The material below was developed to test various divisbility-related methods. Some of this material could be integrated into the `_demonstrations_` page eventually and/or deleted as development continues.
divides_is_bool
# notice that .instance_params and .instance_vars often appear to
# provide the same information for the quantified params/vars:
# really the correct thing
params_example, vars_example = (
divides_is_bool.instance_params,
divides_is_bool.instance_vars)
# But when we have ranges of params like A1 … An
# instance_vars would give A (used more commonly for internal stuff)
# while instance_params would give A1 … An, and is typically what we want
from proveit.logic import Forall
from proveit.core_expr_types import (a_1_to_i, a_1_to_m, b_1_to_j, b_1_to_n,
c_1_to_j, c_1_to_k, c_1_to_n,
d_1_to_k, y_1_to_n)
example_forall = Forall(a_1_to_i, x)
params_example, vars_example = (
example_forall.instance_params,
example_forall.instance_var_or_vars)
two_divides_four = Divides(two, four)
two_divides_four.operands
two_divides_four.lhs
two_divides_four.deduce_in_bool()
two_divides_four_proper = DividesProper(two, four)
InSet(x, Complex).proven(assumptions=[InSet(x, Complex)])
Divides(x, x).conclude(assumptions=[InSet(x, Complex), NotEquals(x, zero)])
try:
Divides(two, two).conclude()
except ProofFailure as e:
print("Proof Failure: {}".format(e))
InSet(two, Complex).prove()
NotEquals(two, zero).prove()
Divides(two, two).conclude()
Divides(two, two).proven()
two_divides_zero = Divides(two, zero)
two_divides_zero.conclude()
Divides(x, zero).conclude(assumptions=[InSet(x, Complex), NotEquals(x, zero)])
# testing general Divide.conclude() method with x|x where we
# have no information about x
try:
Divides(x, x).conclude()
except Exception as e:
print("Exception! {0}".format(e))
# testing general Divide.conclude() method with x|x where we
# now have sufficient information about x
Divides(x, x).conclude(assumptions=[NotEquals(x, zero), InSet(x, Complex)])
# Divides(x, Mult(x, y)).conclude_via_factor(assumptions=[InSet(x, Integer), InSet(y, Integer), NotEquals(x, zero)])
# Divides(x, Mult(y, x)).conclude_via_factor(assumptions=[InSet(x, Integer), InSet(y, Integer), NotEquals(x, zero)])
Divides(x, Mult(x, y)).conclude(assumptions=[InSet(x, Integer), InSet(y, Integer), NotEquals(x, zero)])
Using Divides.conclude() to indirectly utilize transitivity, given the right assumptions:
Divides(x, y).conclude(assumptions=[Divides(x, a), Divides(a, y)])
defaults.assumptions = [Divides(x, a), Divides(a, y)]
Divides(x, y).conclude()
Mult(two, three).deduce_divided_by(two, auto_simplify=False)
Mult(two, three).deduce_divided_by(two)
Mult(two, three).deduce_divided_by(three, auto_simplify=False)
Mult(two, three).deduce_divided_by(three)
# Then a case where the divisibility is clearly not true:
try:
Mult(two, three).deduce_divided_by(four)
except Exception as e:
print("Exception! {0}".format(e))
Divides(Mult(two, three), Mult(two, five)).prove(assumptions=[Divides(Mult(two, three), Mult(two, five))])
Divides(Mult(two, three), Mult(two, five)).eliminate_common_factors(assumptions=[Divides(Mult(two, three), Mult(two, five))])
Divides(Mult(two, three, four), Mult(two, four, five)).eliminate_common_factors(
assumptions=[Divides(Mult(two, three, four), Mult(two, four, five))])
Divides(two, Mult(two, Exp(two, two))).conclude(assumptions=[InSet(Exp(two, two), Integer)])
Divides(Exp(x, n), Exp(y,n)).prove(
assumptions=[Divides(Exp(x, n), Exp(y,n)), InSet(x, Integer), InSet(y, Integer), InSet(n, NaturalPos)])
from proveit.numbers.divisibility import common_factor_elimination
common_factor_elimination
Divides(x, y).prove(
assumptions=[Divides(Exp(x, two), Exp(y,two)), InSet(x, Integer), InSet(y, Integer)])
Divides(Mult(two, x), Mult(two, y)).prove(assumptions=[Divides(Mult(two, x), Mult(two, y))])
Divides(x, y).prove()
# Divides(x, y).prove(
# assumptions=[Divides(Mult(two, x), Mult(two, y)), InSet(x, Integer), InSet(y, Integer)])
GCD(x, y)
GCD(x, y).operands
try:
GCD(x, y).deduce_relatively_prime()
except Exception as e:
print("Exception! {0}".format(e))
GCD(x, y).deduce_relatively_prime(
assumptions=[Equals(GCD(x,y), one), InSet(x, NaturalPos), InSet(y, NaturalPos)])
%end demonstrations