From 0cbb73e9801632ac7314babe26b7065a0a636bc6 Mon Sep 17 00:00:00 2001 From: urojony Date: Fri, 10 Apr 2020 22:44:54 +0200 Subject: [PATCH] first commit --- .ipynb_checkpoints/examples-checkpoint.ipynb | 824 +++++++++++++++++++ __pycache__/shiroindev.cpython-37.pyc | Bin 0 -> 13384 bytes examples.ipynb | 824 +++++++++++++++++++ shiroindev.py | 442 ++++++++++ 4 files changed, 2090 insertions(+) create mode 100644 .ipynb_checkpoints/examples-checkpoint.ipynb create mode 100644 __pycache__/shiroindev.cpython-37.pyc create mode 100644 examples.ipynb create mode 100644 shiroindev.py diff --git a/.ipynb_checkpoints/examples-checkpoint.ipynb b/.ipynb_checkpoints/examples-checkpoint.ipynb new file mode 100644 index 0000000..da4eb5b --- /dev/null +++ b/.ipynb_checkpoints/examples-checkpoint.ipynb @@ -0,0 +1,824 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/grzegorz/shiroindev/shiroindev.py:40: DeprecationWarning: invalid escape sequence \\^\n", + " formula=re.sub('\\^{(.)}',r'^\\1',latex(formula,fold_short_frac=True).replace(' ','').replace('\\\\left(','(').replace('\\\\right)',')'))\n", + "/home/grzegorz/shiroindev/shiroindev.py:41: DeprecationWarning: invalid escape sequence \\{\n", + " return re.sub('\\{(\\(.+?\\))\\}',r'\\1',formula)\n" + ] + } + ], + "source": [ + "from shiroindev import *\n", + "sSeed=1" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The first line obviously loads this package. The second one sets a seed for proving functions. If you don't write it, you can get slightly different proof each time you run a function. \n", + "\n", + "Now let's make some proofs. We will use problems from https://www.imomath.com/index.php?options=593&lmm=0." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Problem 1\n", + "Prove the inequality $a^2+b^2+c^2\\ge ab+bc+ca$, if $a,b,c$ are real numbers." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Function `prove` tries to prove that given formula is nonnegative, **assuming all variables are nonnegative**. In this case the nonnegativity assumption is not a problem, since all powers on the left side are even, so if $|a|^2+|b|^2+|c|^2 \\ge |ab|+|ac|+|bc|,$ then $a^2+b^2+c^2= |a|^2+|b|^2+|c|^2 \\ge |ab|+|ac|+|bc| \\ge ab+ac+bc$." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "numerator: $$a^2-ab-ac+b^2-bc+c^2$$\n", + "denominator: $$1$$\n", + "status: 0\n", + "From weighted AM-GM inequality:\n", + "\n", + "Program couldn't find a solution with integer coefficients. Try to multiple the formula by some integer and run this function again.\n", + "$$ ab+ac+bc \\le \n", + "a^2+b^2+c^2 $$\n" + ] + }, + { + "data": { + "text/plain": [ + "0" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "prove('(a^2+b^2+c^2-a*b-a*c-b*c)')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Function prove prints several things. The first two gives us a formula after expanding it. To proceed, a **numerator** has to be a **polynomial with integer coefficients**. The next one is status, which is the return status of the first use of ```scipy.optimize.linprog```. Possible outputs and explanations are\n", + "\n", + "* 0 - found a proof with real coefficients,\n", + "* 1 - need more time, \n", + "* 2 - function didn't find a proof,\n", + "* 3,4 - loss of precision (which may happen if it has to work with big numbers).\n", + "\n", + "Then we've got a hint. So let's use it!" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "numerator: $$2a^2-2ab-2ac+2b^2-2bc+2c^2$$\n", + "denominator: $$1$$\n", + "status: 0\n", + "From weighted AM-GM inequality:\n", + "$$2ab \\le a^2+b^2$$\n", + "$$2ac \\le a^2+c^2$$\n", + "$$2bc \\le b^2+c^2$$\n", + "\n", + "$$ 0 \\le \n", + "0 $$\n", + "The sum of all inequalities gives us a proof of the inequality.\n" + ] + }, + { + "data": { + "text/plain": [ + "0" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "prove('(a^2+b^2+c^2-a*b-a*c-b*c)*2')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Problem 2\n", + "Find all real numbers such that $a^2+b^2+c^2+d^2=a(b+c+d)$. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "At first glance it doesn't look like an inequality problem, but actually it is one. If you try to calculate both sides for different values, you can see that the left side of the equation is never less than the right one. So let's try" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "numerator: $$a^2-ab-ac-ad+b^2+c^2+d^2$$\n", + "denominator: $$1$$\n", + "status: 2\n", + "\n", + "Program couldn't find any proof.\n", + "$$ ab+ac+ad \\le \n", + "a^2+b^2+c^2+d^2 $$\n" + ] + }, + { + "data": { + "text/plain": [ + "2" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "prove('a^2+b^2+c^2+d^2-a*(b+c+d)')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This time `prove` didn't found the proof. But it doesn't mean that the inequality is not true! `prove` uses a list of values for which the formula should be small. There is no strict rule here, but the smaller that value is, the higher are chances to find a proof. List of values should correspond to the list of variables in alphabetical order. So let's try $a=2$ and $b=c=d=1$." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Substitute $ a \\to 2a $\n", + "numerator: $$4a^2-2ab-2ac-2ad+b^2+c^2+d^2$$\n", + "denominator: $$1$$\n", + "status: 0\n", + "From weighted AM-GM inequality:\n", + "$$2ab \\le a^2+b^2$$\n", + "$$2ac \\le a^2+c^2$$\n", + "$$2ad \\le a^2+d^2$$\n", + "\n", + "$$ 0 \\le \n", + "a^2 $$\n", + "The sum of all inequalities gives us a proof of the inequality.\n" + ] + }, + { + "data": { + "text/plain": [ + "0" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "prove('a^2+b^2+c^2+d^2-a*(b+c+d)','2,1,1,1')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Function makes a substitution $a\\to 2a$ (which should be understood as $a=2a'$) and try to prove new inequality. This time it succeeded. Moreover, if starting formula is equal to 0, then all these inequalities have to be equalities, so $a'^2=0$ and eventually $a=0$. We can also try a little bit lower value for $a$." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Substitute $ a \\to 7a/4 $\n", + "numerator: $$49a^2-28ab-28ac-28ad+16b^2+16c^2+16d^2$$\n", + "denominator: $$16$$\n", + "status: 0\n", + "From weighted AM-GM inequality:\n", + "$$28ab \\le 14a^2+14b^2$$\n", + "$$28ac \\le 14a^2+14c^2$$\n", + "$$28ad \\le 14a^2+14d^2$$\n", + "\n", + "$$ 0 \\le \n", + "7a^2+2b^2+2c^2+2d^2 $$\n", + "The sum of all inequalities gives us a proof of the inequality.\n" + ] + }, + { + "data": { + "text/plain": [ + "0" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "prove('a^2+b^2+c^2+d^2-a*(b+c+d)','7/4,1,1,1')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we can see that if $a^2+b^2+c^2+d^2-a(b+c+d)=0$, then $7a'^2+2b^2+2c^2+2d^2=0$ and eventually $a=b=c=d=0$. Note that inequality is proved only for positive numbers (which, by continuity, can be expanded to nonnegative numbers). But using similar argumentation to the one in previous problem, if $(a,b,c,d)=(x,y,z,t)$ is the solution of $a^2+b^2+c^2+d^2-a(b+c+d)=0$, then $(a,b,c,d)=(|x|,|y|,|z|,|t|)$ is a solution, too. Since the only nonnegative solution is $(0,0,0,0)$, it means that it is the only solution.\n", + "\n", + "Let's skip the problem 3 and look solve the problem 4 instead.\n", + "\n", + "#### Problem 4\n", + "If $x$ and $y$ are two positive numbers less than 1, prove that\n", + "$$\\frac{1}{1-x^2}+\\frac{1}{1-y^2}\\ge \\frac{2}{1-xy}.$$" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "numerator: $$-x^3y+2x^2y^2-x^2-xy^3+2xy-y^2$$\n", + "denominator: $$x^3y^3-x^3y-x^2y^2+x^2-xy^3+xy+y^2-1$$\n", + "status: 2\n", + "\n", + "Program couldn't find any proof.\n", + "$$ x^3y+x^2+xy^3+y^2 \\le \n", + "2x^2y^2+2xy $$\n", + "It looks like the formula is symmetric. You can assume without loss of generality that x >= y Try\n", + "prove(makesubs(S(\" -x**3*y + 2*x**2*y**2 - x**2 - x*y**3 + 2*x*y - y**2 \"), [('y', 'inf')] )\n" + ] + }, + { + "data": { + "text/plain": [ + "2" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "prove('1/(1-x^2)+1/(1-y^2)-2/(1-x*y)')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`prove` assumes that formula is well-defined if all variables are positive, so it doesn't have to analyze the denominator (except of choosing the right sign). In this case it is not true, since if $x=1$, then $1-x^2=0$. Also denominator is equal to $(x^2-1)(y^2-1)(xy-1)$ which is negative for $x,y\\in (0,1)$. So we need to make some substitution after which new variables can have all positive values, not just these inside (0,1) interval.\n", + "\n", + "We will use a function `makesubs` to generate these substitutions. It has three basic parameters: `formula`, `intervals` and `values`. `intervals` are current limitations of variables, `values` are values of variables for which `formula` is small. `values` should be inside corresponding `intervals`. This argument is optional but it's better to use it.\n", + "Let's go back to our problem. If $x=y$, then $\\frac{1}{1-x^2}+\\frac{1}{1-y^2}\\ge \\frac{2}{1-xy}$, so it's the minimum value of the formula. So let `values=(1/2,1/2)` (**warning: do not use decimal point**, for example '0.5,0.5')." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Substitute $ x \\to 1-1/(x+1) $\n", + "Substitute $ y \\to 1-1/(y+1) $\n", + "numerator: $$6x^3y+3x^3-12x^2y^2-3x^2y+3x^2+6xy^3-3xy^2-6xy+3y^3+3y^2$$\n", + "denominator: $$4x^2y+2x^2+4xy^2+8xy+3x+2y^2+3y+1$$\n", + "status: 0\n", + "From weighted AM-GM inequality:\n", + "$$12x^2y^2 \\le 6x^3y+6xy^3$$\n", + "$$3x^2y \\le 2x^3+y^3$$\n", + "$$3xy^2 \\le x^3+2y^3$$\n", + "$$6xy \\le 3x^2+3y^2$$\n", + "\n", + "$$ 0 \\le \n", + "0 $$\n", + "The sum of all inequalities gives us a proof of the inequality.\n" + ] + }, + { + "data": { + "text/plain": [ + "0" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "newformula,newvalues=makesubs('1/(1-x^2)+1/(1-y^2)-2/(1-x*y)','[0,1],[0,1]','1/2,1/2')\n", + "prove(newformula*3,newvalues)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now let's get back to problem 3.\n", + "\n", + "#### Problem 3\n", + "\n", + "If $a,b,c$ are positive real numbers that satisfy $a^2+b^2+c^2=1$, find the minimal value of\n", + "$$\\frac{a^2b^2}{c^2}+\\frac{b^2c^2}{a^2}+\\frac{c^2a^2}{b^2}$$\n", + "\n", + "The problem is equivalent to finding minimum of $xy/z+yz/x+zx/y$ assuming $x+y+z=1$ and $x,y,z>0$. The first idea is to suppose that the minimum is reached when $x=y=z$. In that case, $x=y=z=1/3$ and formula is equal to 1. Now we can substitute $z\\to 1-x-y$. Constraints for variables are $x>0$, $y>0$, $x+y<1$. We can rewrite it as $x \\in (0,1-y)$, $y \\in (0,1)$. These two conditions have two important properties:\n", + "* constraints for variables are written as intervals,\n", + "* there are no \"backwards dependencies\", i.e. there is no $x$ in the interval of $y$.\n", + "\n", + "If these two conditions hold, then you can use `makesubs` function.\n", + "**Warning:** at this moment `makesubs` **doesn't warn you if your list of intervals doesn't follow these rules!**\n" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Substitute $ x \\to -y+1+(y-1)/(x+1) $\n", + "Substitute $ y \\to 1-1/(y+1) $\n", + "Substitute $ y \\to y/2 $\n", + "numerator: $$x^4y^2+x^3y^2-2x^3y-4x^2y+4x^2+xy^2-2xy+y^2$$\n", + "denominator: $$x^3y^2+2x^3y+2x^2y^2+4x^2y+xy^2+2xy$$\n", + "status: 0\n", + "From weighted AM-GM inequality:\n", + "$$2x^3y \\le x^4y^2+x^2$$\n", + "$$4x^2y \\le x^3y^2+2x^2+xy^2$$\n", + "$$2xy \\le x^2+y^2$$\n", + "\n", + "$$ 0 \\le \n", + "0 $$\n", + "The sum of all inequalities gives us a proof of the inequality.\n" + ] + }, + { + "data": { + "text/plain": [ + "0" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "formula=Sm('xy/z+yz/x+zx/y-1').subs('z',S('1-x-y'))\n", + "newformula,values=makesubs(formula,'[0,1-y],[0,1]','1/3,1/3')\n", + "prove(newformula,values)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The proof is found, so the assumption that 1 is the minimum of `xy/z+yz/x+zx/y` was good.\n", + "\n", + "Functions `S` and `Sm` creates a SymPy object from a string. The only difference is that `Sm` assumes that there are no multi-letter variables and adds a multiplication sign between every two terms which has no operator sign, so object `Sm(xy/z+yz/x+zx/y)` has 3 variables `x,y,z` and `S('xy/z+yz/x+zx/y')` has 6 variables `x,y,z,xy,yz,zx`. \n", + "\n", + "As you may have noticed, formulas are often cyclic or symmetric. Therefore you can use `cyclize` or `symmetrize` function to reduce the length of the written formula. Here are a few commands which will do the same as each other. " + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "numerator: $$2a^2-2ab-2ac+2b^2-2bc+2c^2$$\n", + "denominator: $$1$$\n", + "status: 0\n", + "From weighted AM-GM inequality:\n", + "$$2ab \\le a^2+b^2$$\n", + "$$2ac \\le a^2+c^2$$\n", + "$$2bc \\le b^2+c^2$$\n", + "\n", + "$$ 0 \\le \n", + "0 $$\n", + "The sum of all inequalities gives us a proof of the inequality.\n" + ] + }, + { + "data": { + "text/plain": [ + "0" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "prove('(a^2+b^2+c^2-a*b-a*c-b*c)*2')\n", + "#prove(S('(a^2+b^2+c^2-a*b-a*c-b*c)*2'))\n", + "#prove(Sm('2(a^2+b^2+c^2-ab-ac-bc)'))\n", + "#prove(cyclize('2*a^2-2*a*b'))\n", + "#prove(symmetrize('a^2-a*b'))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now look at formula $(x-1)^4$. It's quite obvious that it's nonnegative, but `prove` fails to show this!" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "numerator: $$x^4-4x^3+6x^2-4x+1$$\n", + "denominator: $$1$$\n", + "status: 2\n", + "\n", + "Program couldn't find any proof.\n", + "$$ 4x^3+4x \\le \n", + "x^4+6x^2+1 $$\n" + ] + }, + { + "data": { + "text/plain": [ + "2" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "prove('(x-1)^4')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "But there is a relatively simple method to generate a proof using this library. We will make to proofs: one for $x\\in (1,\\infty)$ and the second one for $(-\\infty,1)$." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Substitute $ x \\to x+1 $\n", + "numerator: $$x^4$$\n", + "denominator: $$1$$\n", + "status: 0\n", + "\n", + "$$ 0 \\le \n", + "x^4 $$\n", + "The sum of all inequalities gives us a proof of the inequality.\n" + ] + }, + { + "data": { + "text/plain": [ + "0" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "prove(makesubs('(x-1)^4','(1,inf)'))" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Substitute $ x \\to 1-x $\n", + "numerator: $$x^4$$\n", + "denominator: $$1$$\n", + "status: 0\n", + "\n", + "$$ 0 \\le \n", + "x^4 $$\n", + "The sum of all inequalities gives us a proof of the inequality.\n" + ] + }, + { + "data": { + "text/plain": [ + "0" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "prove(makesubs('(x-1)^4','(-inf,1)'))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now let's go to the problem 10\n", + "#### Problem 10\n", + "If $a,b,c,d>0$, prove that\n", + "$$\\frac a{b+c}+\\frac b{c+d}+ \\frac c{d+a}+ \\frac d{a+b}\\geq 2.$$\n", + "\n", + "Let's try a simple approach." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "data": { + "text/latex": [ + "$\\displaystyle \\frac{a}{b + c} + \\frac{b}{c + d} + \\frac{c}{a + d} + \\frac{d}{a + b} - 2$" + ], + "text/plain": [ + "a/(b + c) + b/(c + d) + c/(a + d) + d/(a + b) - 2" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "formula=cyclize('a/(b+c)',variables='a,b,c,d')-2\n", + "formula" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "numerator: $$a^3c+a^3d+a^2b^2-a^2bd-2a^2c^2-a^2cd+a^2d^2+ab^3-ab^2c-ab^2d-abc^2+ac^3-acd^2+b^3d+b^2c^2-2b^2d^2+bc^3-bc^2d-bcd^2+bd^3+c^2d^2+cd^3$$\n", + "denominator: $$a^2bc+a^2bd+a^2c^2+a^2cd+ab^2c+ab^2d+abc^2+2abcd+abd^2+ac^2d+acd^2+b^2cd+b^2d^2+bc^2d+bcd^2$$\n", + "status: 2\n", + "\n", + "Program couldn't find any proof.\n", + "$$ a^2bd+2a^2c^2+a^2cd+ab^2c+ab^2d+abc^2+acd^2+2b^2d^2+bc^2d+bcd^2 \\le \n", + "a^3c+a^3d+a^2b^2+a^2d^2+ab^3+ac^3+b^3d+b^2c^2+bc^3+bd^3+c^2d^2+cd^3 $$\n" + ] + }, + { + "data": { + "text/plain": [ + "2" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "prove(formula)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This problem, like the previous one, can be solved by splitting the domain of variables to several subdomains. But we can also use the symmetry of this inequality. For example, without loss of generality we can assume that $a\\ge c$ and $b\\ge d$, so $a\\in [c,\\infty)$, $b\\in [d,\\infty)$." + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Substitute $ a \\to a+c $\n", + "Substitute $ b \\to b+d $\n", + "numerator: $$a^3c+a^3d+a^2b^2+a^2bd+a^2c^2+2a^2cd+a^2d^2+ab^3+ab^2c+2ab^2d-abc^2+abd^2+b^3c+b^3d+b^2c^2+2b^2cd+b^2d^2$$\n", + "denominator: $$a^2bc+a^2bd+a^2c^2+2a^2cd+a^2d^2+ab^2c+ab^2d+3abc^2+6abcd+3abd^2+2ac^3+6ac^2d+6acd^2+2ad^3+b^2c^2+2b^2cd+b^2d^2+2bc^3+6bc^2d+6bcd^2+2bd^3+c^4+4c^3d+6c^2d^2+4cd^3+d^4$$\n", + "status: 0\n", + "From weighted AM-GM inequality:\n", + "\n", + "Program couldn't find a solution with integer coefficients. Try to multiple the formula by some integer and run this function again.\n", + "$$ abc^2 \\le \n", + "a^3c+a^3d+a^2b^2+a^2bd+a^2c^2+2a^2cd+a^2d^2+ab^3+ab^2c+2ab^2d+abd^2+b^3c+b^3d+b^2c^2+2b^2cd+b^2d^2 $$\n" + ] + }, + { + "data": { + "text/plain": [ + "0" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "prove(makesubs(formula,'[c,inf],[d,inf]'))" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Substitute $ a \\to a+c $\n", + "Substitute $ b \\to b+d $\n", + "numerator: $$2a^3c+2a^3d+2a^2b^2+2a^2bd+2a^2c^2+4a^2cd+2a^2d^2+2ab^3+2ab^2c+4ab^2d-2abc^2+2abd^2+2b^3c+2b^3d+2b^2c^2+4b^2cd+2b^2d^2$$\n", + "denominator: $$a^2bc+a^2bd+a^2c^2+2a^2cd+a^2d^2+ab^2c+ab^2d+3abc^2+6abcd+3abd^2+2ac^3+6ac^2d+6acd^2+2ad^3+b^2c^2+2b^2cd+b^2d^2+2bc^3+6bc^2d+6bcd^2+2bd^3+c^4+4c^3d+6c^2d^2+4cd^3+d^4$$\n", + "status: 0\n", + "From weighted AM-GM inequality:\n", + "$$2abc^2 \\le a^2c^2+b^2c^2$$\n", + "\n", + "$$ 0 \\le \n", + "2a^3c+2a^3d+2a^2b^2+2a^2bd+a^2c^2+4a^2cd+2a^2d^2+2ab^3+2ab^2c+4ab^2d+2abd^2+2b^3c+2b^3d+b^2c^2+4b^2cd+2b^2d^2 $$\n", + "The sum of all inequalities gives us a proof of the inequality.\n" + ] + }, + { + "data": { + "text/plain": [ + "0" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "prove(makesubs(formula,'[c,inf],[d,inf]')*2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "It's a good idea to use intervals that are unbounded from one side (i.e. those which contain $\\pm\\infty$). In this problem we could assume that $a\\in (0,c]$, $b\\in (0,d]$ as well. But as you can see, in this case the proof is several times longer." + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Substitute $ a \\to c-c/(a+1) $\n", + "Substitute $ b \\to d-d/(b+1) $\n", + "numerator: $$2a^3bc^2d^2+4a^3bcd^3+2a^3bd^4+2a^3c^2d^2+2a^3cd^3-2a^2b^2c^3d+2a^2b^2cd^3-4a^2bc^3d+4a^2bc^2d^2+12a^2bcd^3+6a^2bd^4-2a^2c^3d+4a^2c^2d^2+6a^2cd^3+2ab^3c^4+4ab^3c^3d+2ab^3c^2d^2+6ab^2c^4+8ab^2c^3d+4ab^2c^2d^2+4ab^2cd^3+6abc^4+4abc^3d+6abc^2d^2+12abcd^3+6abd^4+2ac^4+4ac^2d^2+6acd^3+2b^3c^3d+2b^3c^2d^2+4b^2c^3d+4b^2c^2d^2+2b^2cd^3+2bc^3d+4bc^2d^2+4bcd^3+2bd^4+2c^2d^2+2cd^3$$\n", + "denominator: $$a^3b^3c^4+4a^3b^3c^3d+6a^3b^3c^2d^2+4a^3b^3cd^3+a^3b^3d^4+3a^3b^2c^4+10a^3b^2c^3d+12a^3b^2c^2d^2+6a^3b^2cd^3+a^3b^2d^4+3a^3bc^4+8a^3bc^3d+7a^3bc^2d^2+2a^3bcd^3+a^3c^4+2a^3c^3d+a^3c^2d^2+a^2b^3c^4+6a^2b^3c^3d+12a^2b^3c^2d^2+10a^2b^3cd^3+3a^2b^3d^4+3a^2b^2c^4+15a^2b^2c^3d+24a^2b^2c^2d^2+15a^2b^2cd^3+3a^2b^2d^4+3a^2bc^4+12a^2bc^3d+14a^2bc^2d^2+5a^2bcd^3+a^2c^4+3a^2c^3d+2a^2c^2d^2+2ab^3c^3d+7ab^3c^2d^2+8ab^3cd^3+3ab^3d^4+5ab^2c^3d+14ab^2c^2d^2+12ab^2cd^3+3ab^2d^4+4abc^3d+8abc^2d^2+4abcd^3+ac^3d+ac^2d^2+b^3c^2d^2+2b^3cd^3+b^3d^4+2b^2c^2d^2+3b^2cd^3+b^2d^4+bc^2d^2+bcd^3$$\n", + "status: 0\n", + "From weighted AM-GM inequality:\n", + "$$2a^2b^2c^3d \\le a^3bc^2d^2+ab^3c^4$$\n", + "$$2a^2c^3d \\le a^3c^2d^2+ac^4$$\n", + "$$4a^2bc^3d \\le a^3bc^2d^2+a^3c^2d^2+ab^3c^4+ac^4$$\n", + "\n", + "$$ 0 \\le \n", + "4a^3bcd^3+2a^3bd^4+2a^3cd^3+2a^2b^2cd^3+4a^2bc^2d^2+12a^2bcd^3+6a^2bd^4+4a^2c^2d^2+6a^2cd^3+4ab^3c^3d+2ab^3c^2d^2+6ab^2c^4+8ab^2c^3d+4ab^2c^2d^2+4ab^2cd^3+6abc^4+4abc^3d+6abc^2d^2+12abcd^3+6abd^4+4ac^2d^2+6acd^3+2b^3c^3d+2b^3c^2d^2+4b^2c^3d+4b^2c^2d^2+2b^2cd^3+2bc^3d+4bc^2d^2+4bcd^3+2bd^4+2c^2d^2+2cd^3 $$\n", + "The sum of all inequalities gives us a proof of the inequality.\n" + ] + }, + { + "data": { + "text/plain": [ + "0" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "prove(makesubs(formula,'[0,c],[0,d]')*2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "SageMath 9.0", + "language": "sage", + "name": "sagemath" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/__pycache__/shiroindev.cpython-37.pyc b/__pycache__/shiroindev.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d2c6f2f1976c13e94558623c3d862a2f5d555b7e GIT binary patch literal 13384 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 literal 0 HcmV?d00001 diff --git a/examples.ipynb b/examples.ipynb new file mode 100644 index 0000000..da4eb5b --- /dev/null +++ b/examples.ipynb @@ -0,0 +1,824 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/grzegorz/shiroindev/shiroindev.py:40: DeprecationWarning: invalid escape sequence \\^\n", + " formula=re.sub('\\^{(.)}',r'^\\1',latex(formula,fold_short_frac=True).replace(' ','').replace('\\\\left(','(').replace('\\\\right)',')'))\n", + "/home/grzegorz/shiroindev/shiroindev.py:41: DeprecationWarning: invalid escape sequence \\{\n", + " return re.sub('\\{(\\(.+?\\))\\}',r'\\1',formula)\n" + ] + } + ], + "source": [ + "from shiroindev import *\n", + "sSeed=1" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The first line obviously loads this package. The second one sets a seed for proving functions. If you don't write it, you can get slightly different proof each time you run a function. \n", + "\n", + "Now let's make some proofs. We will use problems from https://www.imomath.com/index.php?options=593&lmm=0." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Problem 1\n", + "Prove the inequality $a^2+b^2+c^2\\ge ab+bc+ca$, if $a,b,c$ are real numbers." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Function `prove` tries to prove that given formula is nonnegative, **assuming all variables are nonnegative**. In this case the nonnegativity assumption is not a problem, since all powers on the left side are even, so if $|a|^2+|b|^2+|c|^2 \\ge |ab|+|ac|+|bc|,$ then $a^2+b^2+c^2= |a|^2+|b|^2+|c|^2 \\ge |ab|+|ac|+|bc| \\ge ab+ac+bc$." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "numerator: $$a^2-ab-ac+b^2-bc+c^2$$\n", + "denominator: $$1$$\n", + "status: 0\n", + "From weighted AM-GM inequality:\n", + "\n", + "Program couldn't find a solution with integer coefficients. Try to multiple the formula by some integer and run this function again.\n", + "$$ ab+ac+bc \\le \n", + "a^2+b^2+c^2 $$\n" + ] + }, + { + "data": { + "text/plain": [ + "0" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "prove('(a^2+b^2+c^2-a*b-a*c-b*c)')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Function prove prints several things. The first two gives us a formula after expanding it. To proceed, a **numerator** has to be a **polynomial with integer coefficients**. The next one is status, which is the return status of the first use of ```scipy.optimize.linprog```. Possible outputs and explanations are\n", + "\n", + "* 0 - found a proof with real coefficients,\n", + "* 1 - need more time, \n", + "* 2 - function didn't find a proof,\n", + "* 3,4 - loss of precision (which may happen if it has to work with big numbers).\n", + "\n", + "Then we've got a hint. So let's use it!" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "numerator: $$2a^2-2ab-2ac+2b^2-2bc+2c^2$$\n", + "denominator: $$1$$\n", + "status: 0\n", + "From weighted AM-GM inequality:\n", + "$$2ab \\le a^2+b^2$$\n", + "$$2ac \\le a^2+c^2$$\n", + "$$2bc \\le b^2+c^2$$\n", + "\n", + "$$ 0 \\le \n", + "0 $$\n", + "The sum of all inequalities gives us a proof of the inequality.\n" + ] + }, + { + "data": { + "text/plain": [ + "0" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "prove('(a^2+b^2+c^2-a*b-a*c-b*c)*2')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Problem 2\n", + "Find all real numbers such that $a^2+b^2+c^2+d^2=a(b+c+d)$. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "At first glance it doesn't look like an inequality problem, but actually it is one. If you try to calculate both sides for different values, you can see that the left side of the equation is never less than the right one. So let's try" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "numerator: $$a^2-ab-ac-ad+b^2+c^2+d^2$$\n", + "denominator: $$1$$\n", + "status: 2\n", + "\n", + "Program couldn't find any proof.\n", + "$$ ab+ac+ad \\le \n", + "a^2+b^2+c^2+d^2 $$\n" + ] + }, + { + "data": { + "text/plain": [ + "2" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "prove('a^2+b^2+c^2+d^2-a*(b+c+d)')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This time `prove` didn't found the proof. But it doesn't mean that the inequality is not true! `prove` uses a list of values for which the formula should be small. There is no strict rule here, but the smaller that value is, the higher are chances to find a proof. List of values should correspond to the list of variables in alphabetical order. So let's try $a=2$ and $b=c=d=1$." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Substitute $ a \\to 2a $\n", + "numerator: $$4a^2-2ab-2ac-2ad+b^2+c^2+d^2$$\n", + "denominator: $$1$$\n", + "status: 0\n", + "From weighted AM-GM inequality:\n", + "$$2ab \\le a^2+b^2$$\n", + "$$2ac \\le a^2+c^2$$\n", + "$$2ad \\le a^2+d^2$$\n", + "\n", + "$$ 0 \\le \n", + "a^2 $$\n", + "The sum of all inequalities gives us a proof of the inequality.\n" + ] + }, + { + "data": { + "text/plain": [ + "0" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "prove('a^2+b^2+c^2+d^2-a*(b+c+d)','2,1,1,1')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Function makes a substitution $a\\to 2a$ (which should be understood as $a=2a'$) and try to prove new inequality. This time it succeeded. Moreover, if starting formula is equal to 0, then all these inequalities have to be equalities, so $a'^2=0$ and eventually $a=0$. We can also try a little bit lower value for $a$." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Substitute $ a \\to 7a/4 $\n", + "numerator: $$49a^2-28ab-28ac-28ad+16b^2+16c^2+16d^2$$\n", + "denominator: $$16$$\n", + "status: 0\n", + "From weighted AM-GM inequality:\n", + "$$28ab \\le 14a^2+14b^2$$\n", + "$$28ac \\le 14a^2+14c^2$$\n", + "$$28ad \\le 14a^2+14d^2$$\n", + "\n", + "$$ 0 \\le \n", + "7a^2+2b^2+2c^2+2d^2 $$\n", + "The sum of all inequalities gives us a proof of the inequality.\n" + ] + }, + { + "data": { + "text/plain": [ + "0" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "prove('a^2+b^2+c^2+d^2-a*(b+c+d)','7/4,1,1,1')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we can see that if $a^2+b^2+c^2+d^2-a(b+c+d)=0$, then $7a'^2+2b^2+2c^2+2d^2=0$ and eventually $a=b=c=d=0$. Note that inequality is proved only for positive numbers (which, by continuity, can be expanded to nonnegative numbers). But using similar argumentation to the one in previous problem, if $(a,b,c,d)=(x,y,z,t)$ is the solution of $a^2+b^2+c^2+d^2-a(b+c+d)=0$, then $(a,b,c,d)=(|x|,|y|,|z|,|t|)$ is a solution, too. Since the only nonnegative solution is $(0,0,0,0)$, it means that it is the only solution.\n", + "\n", + "Let's skip the problem 3 and look solve the problem 4 instead.\n", + "\n", + "#### Problem 4\n", + "If $x$ and $y$ are two positive numbers less than 1, prove that\n", + "$$\\frac{1}{1-x^2}+\\frac{1}{1-y^2}\\ge \\frac{2}{1-xy}.$$" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "numerator: $$-x^3y+2x^2y^2-x^2-xy^3+2xy-y^2$$\n", + "denominator: $$x^3y^3-x^3y-x^2y^2+x^2-xy^3+xy+y^2-1$$\n", + "status: 2\n", + "\n", + "Program couldn't find any proof.\n", + "$$ x^3y+x^2+xy^3+y^2 \\le \n", + "2x^2y^2+2xy $$\n", + "It looks like the formula is symmetric. You can assume without loss of generality that x >= y Try\n", + "prove(makesubs(S(\" -x**3*y + 2*x**2*y**2 - x**2 - x*y**3 + 2*x*y - y**2 \"), [('y', 'inf')] )\n" + ] + }, + { + "data": { + "text/plain": [ + "2" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "prove('1/(1-x^2)+1/(1-y^2)-2/(1-x*y)')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`prove` assumes that formula is well-defined if all variables are positive, so it doesn't have to analyze the denominator (except of choosing the right sign). In this case it is not true, since if $x=1$, then $1-x^2=0$. Also denominator is equal to $(x^2-1)(y^2-1)(xy-1)$ which is negative for $x,y\\in (0,1)$. So we need to make some substitution after which new variables can have all positive values, not just these inside (0,1) interval.\n", + "\n", + "We will use a function `makesubs` to generate these substitutions. It has three basic parameters: `formula`, `intervals` and `values`. `intervals` are current limitations of variables, `values` are values of variables for which `formula` is small. `values` should be inside corresponding `intervals`. This argument is optional but it's better to use it.\n", + "Let's go back to our problem. If $x=y$, then $\\frac{1}{1-x^2}+\\frac{1}{1-y^2}\\ge \\frac{2}{1-xy}$, so it's the minimum value of the formula. So let `values=(1/2,1/2)` (**warning: do not use decimal point**, for example '0.5,0.5')." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Substitute $ x \\to 1-1/(x+1) $\n", + "Substitute $ y \\to 1-1/(y+1) $\n", + "numerator: $$6x^3y+3x^3-12x^2y^2-3x^2y+3x^2+6xy^3-3xy^2-6xy+3y^3+3y^2$$\n", + "denominator: $$4x^2y+2x^2+4xy^2+8xy+3x+2y^2+3y+1$$\n", + "status: 0\n", + "From weighted AM-GM inequality:\n", + "$$12x^2y^2 \\le 6x^3y+6xy^3$$\n", + "$$3x^2y \\le 2x^3+y^3$$\n", + "$$3xy^2 \\le x^3+2y^3$$\n", + "$$6xy \\le 3x^2+3y^2$$\n", + "\n", + "$$ 0 \\le \n", + "0 $$\n", + "The sum of all inequalities gives us a proof of the inequality.\n" + ] + }, + { + "data": { + "text/plain": [ + "0" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "newformula,newvalues=makesubs('1/(1-x^2)+1/(1-y^2)-2/(1-x*y)','[0,1],[0,1]','1/2,1/2')\n", + "prove(newformula*3,newvalues)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now let's get back to problem 3.\n", + "\n", + "#### Problem 3\n", + "\n", + "If $a,b,c$ are positive real numbers that satisfy $a^2+b^2+c^2=1$, find the minimal value of\n", + "$$\\frac{a^2b^2}{c^2}+\\frac{b^2c^2}{a^2}+\\frac{c^2a^2}{b^2}$$\n", + "\n", + "The problem is equivalent to finding minimum of $xy/z+yz/x+zx/y$ assuming $x+y+z=1$ and $x,y,z>0$. The first idea is to suppose that the minimum is reached when $x=y=z$. In that case, $x=y=z=1/3$ and formula is equal to 1. Now we can substitute $z\\to 1-x-y$. Constraints for variables are $x>0$, $y>0$, $x+y<1$. We can rewrite it as $x \\in (0,1-y)$, $y \\in (0,1)$. These two conditions have two important properties:\n", + "* constraints for variables are written as intervals,\n", + "* there are no \"backwards dependencies\", i.e. there is no $x$ in the interval of $y$.\n", + "\n", + "If these two conditions hold, then you can use `makesubs` function.\n", + "**Warning:** at this moment `makesubs` **doesn't warn you if your list of intervals doesn't follow these rules!**\n" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Substitute $ x \\to -y+1+(y-1)/(x+1) $\n", + "Substitute $ y \\to 1-1/(y+1) $\n", + "Substitute $ y \\to y/2 $\n", + "numerator: $$x^4y^2+x^3y^2-2x^3y-4x^2y+4x^2+xy^2-2xy+y^2$$\n", + "denominator: $$x^3y^2+2x^3y+2x^2y^2+4x^2y+xy^2+2xy$$\n", + "status: 0\n", + "From weighted AM-GM inequality:\n", + "$$2x^3y \\le x^4y^2+x^2$$\n", + "$$4x^2y \\le x^3y^2+2x^2+xy^2$$\n", + "$$2xy \\le x^2+y^2$$\n", + "\n", + "$$ 0 \\le \n", + "0 $$\n", + "The sum of all inequalities gives us a proof of the inequality.\n" + ] + }, + { + "data": { + "text/plain": [ + "0" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "formula=Sm('xy/z+yz/x+zx/y-1').subs('z',S('1-x-y'))\n", + "newformula,values=makesubs(formula,'[0,1-y],[0,1]','1/3,1/3')\n", + "prove(newformula,values)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The proof is found, so the assumption that 1 is the minimum of `xy/z+yz/x+zx/y` was good.\n", + "\n", + "Functions `S` and `Sm` creates a SymPy object from a string. The only difference is that `Sm` assumes that there are no multi-letter variables and adds a multiplication sign between every two terms which has no operator sign, so object `Sm(xy/z+yz/x+zx/y)` has 3 variables `x,y,z` and `S('xy/z+yz/x+zx/y')` has 6 variables `x,y,z,xy,yz,zx`. \n", + "\n", + "As you may have noticed, formulas are often cyclic or symmetric. Therefore you can use `cyclize` or `symmetrize` function to reduce the length of the written formula. Here are a few commands which will do the same as each other. " + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "numerator: $$2a^2-2ab-2ac+2b^2-2bc+2c^2$$\n", + "denominator: $$1$$\n", + "status: 0\n", + "From weighted AM-GM inequality:\n", + "$$2ab \\le a^2+b^2$$\n", + "$$2ac \\le a^2+c^2$$\n", + "$$2bc \\le b^2+c^2$$\n", + "\n", + "$$ 0 \\le \n", + "0 $$\n", + "The sum of all inequalities gives us a proof of the inequality.\n" + ] + }, + { + "data": { + "text/plain": [ + "0" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "prove('(a^2+b^2+c^2-a*b-a*c-b*c)*2')\n", + "#prove(S('(a^2+b^2+c^2-a*b-a*c-b*c)*2'))\n", + "#prove(Sm('2(a^2+b^2+c^2-ab-ac-bc)'))\n", + "#prove(cyclize('2*a^2-2*a*b'))\n", + "#prove(symmetrize('a^2-a*b'))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now look at formula $(x-1)^4$. It's quite obvious that it's nonnegative, but `prove` fails to show this!" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "numerator: $$x^4-4x^3+6x^2-4x+1$$\n", + "denominator: $$1$$\n", + "status: 2\n", + "\n", + "Program couldn't find any proof.\n", + "$$ 4x^3+4x \\le \n", + "x^4+6x^2+1 $$\n" + ] + }, + { + "data": { + "text/plain": [ + "2" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "prove('(x-1)^4')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "But there is a relatively simple method to generate a proof using this library. We will make to proofs: one for $x\\in (1,\\infty)$ and the second one for $(-\\infty,1)$." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Substitute $ x \\to x+1 $\n", + "numerator: $$x^4$$\n", + "denominator: $$1$$\n", + "status: 0\n", + "\n", + "$$ 0 \\le \n", + "x^4 $$\n", + "The sum of all inequalities gives us a proof of the inequality.\n" + ] + }, + { + "data": { + "text/plain": [ + "0" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "prove(makesubs('(x-1)^4','(1,inf)'))" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Substitute $ x \\to 1-x $\n", + "numerator: $$x^4$$\n", + "denominator: $$1$$\n", + "status: 0\n", + "\n", + "$$ 0 \\le \n", + "x^4 $$\n", + "The sum of all inequalities gives us a proof of the inequality.\n" + ] + }, + { + "data": { + "text/plain": [ + "0" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "prove(makesubs('(x-1)^4','(-inf,1)'))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now let's go to the problem 10\n", + "#### Problem 10\n", + "If $a,b,c,d>0$, prove that\n", + "$$\\frac a{b+c}+\\frac b{c+d}+ \\frac c{d+a}+ \\frac d{a+b}\\geq 2.$$\n", + "\n", + "Let's try a simple approach." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "data": { + "text/latex": [ + "$\\displaystyle \\frac{a}{b + c} + \\frac{b}{c + d} + \\frac{c}{a + d} + \\frac{d}{a + b} - 2$" + ], + "text/plain": [ + "a/(b + c) + b/(c + d) + c/(a + d) + d/(a + b) - 2" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "formula=cyclize('a/(b+c)',variables='a,b,c,d')-2\n", + "formula" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "numerator: $$a^3c+a^3d+a^2b^2-a^2bd-2a^2c^2-a^2cd+a^2d^2+ab^3-ab^2c-ab^2d-abc^2+ac^3-acd^2+b^3d+b^2c^2-2b^2d^2+bc^3-bc^2d-bcd^2+bd^3+c^2d^2+cd^3$$\n", + "denominator: $$a^2bc+a^2bd+a^2c^2+a^2cd+ab^2c+ab^2d+abc^2+2abcd+abd^2+ac^2d+acd^2+b^2cd+b^2d^2+bc^2d+bcd^2$$\n", + "status: 2\n", + "\n", + "Program couldn't find any proof.\n", + "$$ a^2bd+2a^2c^2+a^2cd+ab^2c+ab^2d+abc^2+acd^2+2b^2d^2+bc^2d+bcd^2 \\le \n", + "a^3c+a^3d+a^2b^2+a^2d^2+ab^3+ac^3+b^3d+b^2c^2+bc^3+bd^3+c^2d^2+cd^3 $$\n" + ] + }, + { + "data": { + "text/plain": [ + "2" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "prove(formula)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This problem, like the previous one, can be solved by splitting the domain of variables to several subdomains. But we can also use the symmetry of this inequality. For example, without loss of generality we can assume that $a\\ge c$ and $b\\ge d$, so $a\\in [c,\\infty)$, $b\\in [d,\\infty)$." + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Substitute $ a \\to a+c $\n", + "Substitute $ b \\to b+d $\n", + "numerator: $$a^3c+a^3d+a^2b^2+a^2bd+a^2c^2+2a^2cd+a^2d^2+ab^3+ab^2c+2ab^2d-abc^2+abd^2+b^3c+b^3d+b^2c^2+2b^2cd+b^2d^2$$\n", + "denominator: $$a^2bc+a^2bd+a^2c^2+2a^2cd+a^2d^2+ab^2c+ab^2d+3abc^2+6abcd+3abd^2+2ac^3+6ac^2d+6acd^2+2ad^3+b^2c^2+2b^2cd+b^2d^2+2bc^3+6bc^2d+6bcd^2+2bd^3+c^4+4c^3d+6c^2d^2+4cd^3+d^4$$\n", + "status: 0\n", + "From weighted AM-GM inequality:\n", + "\n", + "Program couldn't find a solution with integer coefficients. Try to multiple the formula by some integer and run this function again.\n", + "$$ abc^2 \\le \n", + "a^3c+a^3d+a^2b^2+a^2bd+a^2c^2+2a^2cd+a^2d^2+ab^3+ab^2c+2ab^2d+abd^2+b^3c+b^3d+b^2c^2+2b^2cd+b^2d^2 $$\n" + ] + }, + { + "data": { + "text/plain": [ + "0" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "prove(makesubs(formula,'[c,inf],[d,inf]'))" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Substitute $ a \\to a+c $\n", + "Substitute $ b \\to b+d $\n", + "numerator: $$2a^3c+2a^3d+2a^2b^2+2a^2bd+2a^2c^2+4a^2cd+2a^2d^2+2ab^3+2ab^2c+4ab^2d-2abc^2+2abd^2+2b^3c+2b^3d+2b^2c^2+4b^2cd+2b^2d^2$$\n", + "denominator: $$a^2bc+a^2bd+a^2c^2+2a^2cd+a^2d^2+ab^2c+ab^2d+3abc^2+6abcd+3abd^2+2ac^3+6ac^2d+6acd^2+2ad^3+b^2c^2+2b^2cd+b^2d^2+2bc^3+6bc^2d+6bcd^2+2bd^3+c^4+4c^3d+6c^2d^2+4cd^3+d^4$$\n", + "status: 0\n", + "From weighted AM-GM inequality:\n", + "$$2abc^2 \\le a^2c^2+b^2c^2$$\n", + "\n", + "$$ 0 \\le \n", + "2a^3c+2a^3d+2a^2b^2+2a^2bd+a^2c^2+4a^2cd+2a^2d^2+2ab^3+2ab^2c+4ab^2d+2abd^2+2b^3c+2b^3d+b^2c^2+4b^2cd+2b^2d^2 $$\n", + "The sum of all inequalities gives us a proof of the inequality.\n" + ] + }, + { + "data": { + "text/plain": [ + "0" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "prove(makesubs(formula,'[c,inf],[d,inf]')*2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "It's a good idea to use intervals that are unbounded from one side (i.e. those which contain $\\pm\\infty$). In this problem we could assume that $a\\in (0,c]$, $b\\in (0,d]$ as well. But as you can see, in this case the proof is several times longer." + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Substitute $ a \\to c-c/(a+1) $\n", + "Substitute $ b \\to d-d/(b+1) $\n", + "numerator: $$2a^3bc^2d^2+4a^3bcd^3+2a^3bd^4+2a^3c^2d^2+2a^3cd^3-2a^2b^2c^3d+2a^2b^2cd^3-4a^2bc^3d+4a^2bc^2d^2+12a^2bcd^3+6a^2bd^4-2a^2c^3d+4a^2c^2d^2+6a^2cd^3+2ab^3c^4+4ab^3c^3d+2ab^3c^2d^2+6ab^2c^4+8ab^2c^3d+4ab^2c^2d^2+4ab^2cd^3+6abc^4+4abc^3d+6abc^2d^2+12abcd^3+6abd^4+2ac^4+4ac^2d^2+6acd^3+2b^3c^3d+2b^3c^2d^2+4b^2c^3d+4b^2c^2d^2+2b^2cd^3+2bc^3d+4bc^2d^2+4bcd^3+2bd^4+2c^2d^2+2cd^3$$\n", + "denominator: $$a^3b^3c^4+4a^3b^3c^3d+6a^3b^3c^2d^2+4a^3b^3cd^3+a^3b^3d^4+3a^3b^2c^4+10a^3b^2c^3d+12a^3b^2c^2d^2+6a^3b^2cd^3+a^3b^2d^4+3a^3bc^4+8a^3bc^3d+7a^3bc^2d^2+2a^3bcd^3+a^3c^4+2a^3c^3d+a^3c^2d^2+a^2b^3c^4+6a^2b^3c^3d+12a^2b^3c^2d^2+10a^2b^3cd^3+3a^2b^3d^4+3a^2b^2c^4+15a^2b^2c^3d+24a^2b^2c^2d^2+15a^2b^2cd^3+3a^2b^2d^4+3a^2bc^4+12a^2bc^3d+14a^2bc^2d^2+5a^2bcd^3+a^2c^4+3a^2c^3d+2a^2c^2d^2+2ab^3c^3d+7ab^3c^2d^2+8ab^3cd^3+3ab^3d^4+5ab^2c^3d+14ab^2c^2d^2+12ab^2cd^3+3ab^2d^4+4abc^3d+8abc^2d^2+4abcd^3+ac^3d+ac^2d^2+b^3c^2d^2+2b^3cd^3+b^3d^4+2b^2c^2d^2+3b^2cd^3+b^2d^4+bc^2d^2+bcd^3$$\n", + "status: 0\n", + "From weighted AM-GM inequality:\n", + "$$2a^2b^2c^3d \\le a^3bc^2d^2+ab^3c^4$$\n", + "$$2a^2c^3d \\le a^3c^2d^2+ac^4$$\n", + "$$4a^2bc^3d \\le a^3bc^2d^2+a^3c^2d^2+ab^3c^4+ac^4$$\n", + "\n", + "$$ 0 \\le \n", + "4a^3bcd^3+2a^3bd^4+2a^3cd^3+2a^2b^2cd^3+4a^2bc^2d^2+12a^2bcd^3+6a^2bd^4+4a^2c^2d^2+6a^2cd^3+4ab^3c^3d+2ab^3c^2d^2+6ab^2c^4+8ab^2c^3d+4ab^2c^2d^2+4ab^2cd^3+6abc^4+4abc^3d+6abc^2d^2+12abcd^3+6abd^4+4ac^2d^2+6acd^3+2b^3c^3d+2b^3c^2d^2+4b^2c^3d+4b^2c^2d^2+2b^2cd^3+2bc^3d+4bc^2d^2+4bcd^3+2bd^4+2c^2d^2+2cd^3 $$\n", + "The sum of all inequalities gives us a proof of the inequality.\n" + ] + }, + { + "data": { + "text/plain": [ + "0" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "prove(makesubs(formula,'[0,c],[0,d]')*2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "SageMath 9.0", + "language": "sage", + "name": "sagemath" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/shiroindev.py b/shiroindev.py new file mode 100644 index 0000000..ca1e3c2 --- /dev/null +++ b/shiroindev.py @@ -0,0 +1,442 @@ +from __future__ import print_function +import warnings,operator +warnings.filterwarnings("ignore") +#Seed is needed to select the weights in linprog function. +#None means that the seed is random. +sSeed=None +sTranslation={} +translationList=['numerator:','denominator:','status:', +'Substitute',"Formula after substitution:", +"Numerator after substitutions:","From weighted AM-GM inequality:", +'The sum of all inequalities gives us a proof of the inequality.', +"Program couldn't find a solution with integer coefficients. Try "+ +"to multiple the formula by some integer and run this function again.", +"Program couldn't find any proof.", +"Try to set higher linprogiter parameter.", +"It looks like the formula is symmetric. You can assume without loss of"+ +" generality that ","Try" +] +#Initialize english-english dictionary. +for phrase in translationList: + sTranslation[phrase]=phrase +from scipy.optimize import linprog +import random +from sympy import S,cancel,fraction,Pow,expand,solve,latex +import re +def _remzero(coef,fun): +#coef, fun represents an expression. +#For example, if expression=5f(2,3)+0f(4,6)+8f(1,4) +#then coef=[5,0,8], fun=[[2,3],[4,6],[1,4]] +#_remzero removes addends with coefficient equal to zero. +#In this example ncoef=[5,8], nfun=[[2,3],[1,4]] + ncoef=[] + nfun=[] + for c,f in zip(coef,fun): + if c>0: + ncoef+=[c] + nfun+=[f] + return ncoef,nfun +def slatex(formula): #fancy function which makes latex code more readable, but still correct + formula=re.sub('\^{(.)}',r'^\1',latex(formula,fold_short_frac=True).replace(' ','').replace('\\left(','(').replace('\\right)',')')) + return re.sub('\{(\(.+?\))\}',r'\1',formula) +def _writ2(coef,fun,variables): + return slatex(S((str(coef)+'*'+'*'.join([str(x)+'^'+str(y) for x,y in zip(variables,fun)])))) +def _writ(coef,fun,nullvar): + return str(coef)+'f('+str(fun)[1:-1-(len(fun)==1)]+')' +def _check(coef,fun,res,rfun): +#checks if rounding and all the floating point stuff works + res2=[int(round(x)) for x in res] + b1=[coef*x for x in fun] + b2=[[x*y for y in rfuni] for x,rfuni in zip(res2,rfun)] + return b1==[sum(x) for x in zip(*b2)] and coef==sum(res2) +def _powr(formula): + if formula.func==Pow: + return formula.args + else: + return [formula,S('1')] +def fractioncancel(formula): +#workaround for buggy cancel function + num,den=fraction(cancel(formula/S('tmp'))) + den=den.subs('tmp','1') + return num,den +def ssolve(formula,variables): +#workaround for inconsistent solve function + result=solve(formula,variables) + if type(result)==dict: + result=[[result[var] for var in variables]] + return result +def sstr(formula): + return str(formula).replace('**','^').replace('*','').replace(' ','') +def Sm(formula): +#Adds multiplication signs and sympifies a formula. +#For example, Sm('(2x+y)(7+5xz)') -> S('(2*x+y)*(7+5*x*z)') + if type(formula)==str: + formula.replace(' ','') + for i in range(2): + formula=re.sub(r'([0-9a-zA-Z)])([(a-zA-Z])',r'\1*\2',formula) + formula=S(formula) + return formula +def _input2fraction(formula,variables,values): +#makes some substitutions and converts formula to a fraction +#with expanded numerator and denominator + formula=S(formula) + subst=[] + for x,y in zip(variables,values): + if y!=1: + print(sTranslation['Substitute'],'$',x,'\\to',slatex(S(y)*S(x)),'$') + subst+=[(x,x*y)] + formula=formula.subs(subst) + numerator,denominator=fractioncancel(formula) + print(sTranslation['numerator:'],'$$'+slatex(numerator)+'$$') + print(sTranslation['denominator:'],'$$'+slatex(denominator)+'$$') + return (numerator,denominator) +def _formula2list(formula,variables): +#Splits a polynomial to a difference of two polynomials with positive +#coefficients and extracts coefficients and powers of both polynomials. +#'variables' is used to set order of powers +#For example, If formula=5x^2-4xy+8y^3, variables=[x,y], then +#the program tries to prove that +#0<=5x^2-4xy+8y^3 +#4xy<=5x^2+8y^3 +#lcoef=[4] +#lfun=[[1,1]] +#rcoef=[5,8] +#rfun=[[2,0],[0,3]] + lfun=[] + lcoef=[] + rfun=[] + rcoef=[] + varorder=dict(zip(variables,range(len(variables)))) + for addend in formula.as_ordered_terms(): + coef,facts=addend.as_coeff_mul() + powers=[0]*len(variables) + for var in variables: + powers[varorder[var]]=0 + for fact in facts: + var,pw=_powr(fact) + powers[varorder[var]]=int(pw) + if(coef<0): + lcoef+=[-coef] + lfun+=[powers] + else: + rcoef+=[coef] + rfun+=[powers] + return(lcoef,lfun,rcoef,rfun) +def _list2proof(lcoef,lfun,rcoef,rfun,variables,itermax,linprogiter,_writ2=_writ2): +#Now the formula is splitted on two polynomials with positive coefficients. +#we will call them LHS and RHS and our inequality to prove would +#be LHS<=RHS (instead of 0<=RHS-LHS). + +#suppose we are trying to prove that +#30x^2y^2+60xy^4<=48x^3+56y^6 (assuming x,y>0) +#program will try to find some a,b,c,d such that +#30x^2y^2<=ax^3+by^6 +#60xy^4<=cx^3+dy^6 +#where a+c<=48 and b+d<=56 (assumption 1) +#We need some additional equalities to meet assumptions +#of the weighted AM-GM inequality. +#a+b=30 and c+d=60 (assumption 2) +#3a+0b=30*2, 0a+6b=30*2, 3c+0d=60*1, 0c+6d=60*4 (assumption 3) + +#The sketch of the algorithm. +# for i in range(itermax): + #1. Create a vector of random numbers (weights). + #2. Try to find real solution of the problem (with linprog). + #3. If there is no solution (status: 2) + #3a. If the solution was never found, break. + #3b. Else, step back (to the bigger inequality) + #4. If the soltuion was found (status: 0) + #Check out which of variables (in example: a,b,c,d) looks like integer. + #If there are some inequalities with all integer coefficients, subtract + #them from the original one. + #If LHS is empty, then break. + localseed=sSeed + bufer='' + itern=0 + if len(lcoef)==0: #if LHS is empty + print(sTranslation['status:'], 0) + status=0 + elif len(rcoef)==0: + #if RHS is empty, but LHS is not + print(sTranslation['status:'], 2) + status=2 + itermax=0 + foundreal=0 + while len(lcoef)>0 and itern0.0001): + break + else: + #checks if rounding all coefficients doesn't make + #inequality false + isok=_check(lcoef[i],lfun[i],res.x[i*n:i*n+n],rfun) + if not isok: + continue + bufer+='$$'+_writ2(lcoef[i],lfun[i],variables)+' \\le ' + lcoef[i]=0 + for j in range(n): + rcoef[j]-=int(round(res.x[i*n+j])) + for j,k in zip(res.x[i*n:i*n+n],rfun): + if j<0.0001: + continue + if(c):bufer+='+' + else:c=1 + bufer+=_writ2(int(round(j)),k,variables) + bufer+='$$\n' + lcoef,lfun=_remzero(lcoef,lfun) + rcoef,rfun=_remzero(rcoef,rfun) + print(bufer) + lhs='+'.join([_writ2(c,f,variables) for c,f in zip(lcoef,lfun)]) + if lhs=='': + lhs='0' + elif status==0: + print(sTranslation[ + "Program couldn't find a solution with integer coefficients. Try "+ + "to multiple the formula by some integer and run this function again."]) + elif(status==2): + print(sTranslation["Program couldn't find any proof."]) + #return res.status + elif status==1: + print(sTranslation["Try to set higher linprogiter parameter."]) + print('$$ ',slatex(lhs),' \\le ') + rhs='+'.join([_writ2(c,f,variables) for c,f in zip(rcoef,rfun)]) + if rhs=='': + rhs='0' + print(slatex(rhs),' $$') + if lhs=='0': + print(sTranslation['The sum of all inequalities gives us a proof of the inequality.']) + return status +def _isiterable(obj): + try: + _ = (e for e in obj) + return True + except TypeError: + return False +def _smakeiterable(x): + x=S(x) + if _isiterable(x): + return x + return (x,) +def _smakeiterable2(x): + x=S(x) + if _isiterable(x[0]): + return x + return (x,) +def prove(formula,values=None,variables=None,niter=200,linprogiter=10000): +#tries to prove that formula>=0 assuming all variables are positive + formula=S(formula) + if variables: variables=_smakeiterable(variables) + else: variables=sorted(formula.free_symbols,key=str) + if values: values=_smakeiterable(values) + else: values=[1]*len(variables) + num,den=_input2fraction(formula,variables,values) + st=_list2proof(*(_formula2list(num,variables)+(variables,niter,linprogiter))) + if st==2 and issymetric(num): + fs=sorted([str(x) for x in num.free_symbols]) + print(sTranslation["It looks like the formula is symmetric. "+ + "You can assume without loss of generality that "], + ' >= '.join([str(x) for x in fs]),sTranslation['Try']) + print('prove(makesubs(S("',num,'"),', + [(str(x),'inf') for x in variables[1:]],')') + return st +def powerprove(formula,values=None,variables=None,niter=200,linprogiter=10000): +#This is a bruteforce and ineffective function for proving inequalities. +#It can be used as the last resort. + formula=S(formula) + if variables: variables=_smakeiterable(variables) + else: variables=sorted(formula.free_symbols,key=str) + if values: values=_smakeiterable(values) + else: values=[1]*len(variables) + num,den=_input2fraction(formula,variables,values) + subst2=[] + for j in range(len(variables)): + subst2+=[(variables[j],1+variables[j])] + for i in range(1<R instead of a polynomial. provef checks if a formula +#is nonnegative for any nonnegative and convex function f. If so, it +#provides a proof of nonnegativity. + formula=S(formula) + num,den=_input2fraction(formula,[],[]) + _list2proof(*(_formula2listf(num)+(None,niter,linprogiter,_writ))) +def issymetric(formula): #checks if formula is symmetric +#and has at least two variables + if len(formula.free_symbols)<2: + return False + ls=list(formula.free_symbols) + a=ls[0] + for b in ls[1:]: + if expand(formula-formula.subs({a:b, b:a}, simultaneous=True))!=S(0): + return False + return True +def cyclize(formula,oper=operator.add,variables=None,init=None): +#cyclize('a^2*b')=S('a^2*b+b^2*a') +#cyclize('a^2*b',variables='a,b,c')=S('a^2*b+b^2*c+c^2*a') + formula=S(formula) + if variables==None: + variables=sorted(formula.free_symbols,key=str) + else: + variables=S(variables) + if len(variables)==0: + return init + variables=list(variables) #if variables is a tuple, change it to a list + variables+=[variables[0]] + subst=list(zip(variables[:-1],variables[1:])) + if init==None: + init=formula + else: + init=oper(init,formula) + for _ in variables[2:]: + formula=formula.subs(subst,simultaneous=True) + init=oper(init,formula) + return init +def symmetrize(formula,oper=operator.add,variables=None,init=None): +#symmetrize('a^2*b')=S('a^2*b+b^2*a') +#symmetrize('a^2*b',variables='a,b,c')= +#=S('a^2*b+a^2*c+b^2*a+b^2*c+c^2*a+c^2*b') + formula=S(formula) + if variables==None: + variables=sorted(formula.free_symbols,key=str) + else: + variables=S(variables) + for i in range(1,len(variables)): + formula=cyclize(formula,oper,variables[:i+1]) + return formula