This is a continuation of my previous post on beta distribution.
My colleague Tilo wants me to use Sagemath instead of Mathematica, which turns out to be much harder. But now I have done it and we have a completely open source proof.
This is written in a Jupyter note book which can be downloaded here.
NoneSome setup¶
import sympy
x,a,b,x1,B=SR.var('x,a,b, x1,B')
f(x)=x^(a-1)*(1-x)^(b-1)/beta(a,b)
The peak of $f(x)$ is at
m(a,b)=(a-1)/(a+b-2);
m(a,b).show()
We see this from a picture
f_ex(x) = f(x).subs(a==3).subs(b==7);
m_ex = m(3,7);
plot(f_ex(x),(x,0,1))+line([(m_ex,0),(m_ex,f_ex(m_ex))], color='red',linestyle='--')
We define $f^{-1}(x)$ to be the inverse of left and right side of $f(x)$ for $1>x>m(a,b)$ and $m(a,b)>x>0$ respectively.
finv=function('finv', latex_name="f^{-1}")
Let $r(x)=f(f^{-1}(x))$, which reflects a point $x$ to throught the curve of $f(x)$. We want to show that $r(x)$ is convex if $b>a>1$. See my previous post for pictures.
r(x)=finv(f(x))
r(x).show()
This is $f(x)$'s direvative.
df(x)=diff(f(x),x).combine();
df(x).show()
This is $f^{-1}(x)$'s direvative.
dfinv(x)=1/df(finv(x));
dfinv(x).show()
First direvative of $r(x)$¶
rd1=diff(r(x),x);
rd1.show()
to_be_replace=rd1.operands()[1];
to_be_replace.show()
rd1_0=rd1.subs(to_be_replace==dfinv(f(x)));
rd1_0.show()
Make it a easier to manipulate by changing some symbobls. Let $B=\beta(a,b)$ and $x_1$ be the reflection point of $x$.
rd1_1=rd1_0.subs(finv(f(x))==x1).subs(beta(a,b)==B);
rd1_1.show()
Simplify using sympy.
rd1_2=rd1_1._sympy_().simplify()._sage_();
rd1_2.show()
Note that we have three equalities.
eq1=beta(a,b)*f(x)==beta(a,b)*f(x1);
eq1.show()
eq2=eq1.op[1]/eq1.op[1,1]==eq1.op[0]/eq1.op[1,1];
eq2.show()
eq3=eq1.op[1]/eq1.op[1,0]==eq1.op[0]/eq1.op[1,0];
eq3.show()
Now we simplify again use these equations.
rd1_3=rd1_2._sympy_().subs(eq2.op[0],eq2.op[1]).subs(eq3.op[0],eq3.op[1]).simplify().together()._sage_()
rd1_3.show()
The final form for $r'(x)$ is
rd1_4=rd1_3.subs(x1==finv(f(x)));
rd1_4.show()
Second direvative¶
rd2_0=rd1_4.diff(x);
[o.show() for o in rd2_0.op[0].op];
to_be_replace_2=rd2_0.op[0].op[-1];
to_be_replace_2.show();
rd2_1=rd2_0.subs(to_be_replace_2==dfinv(f(x))).subs(finv(f(x))==x1).subs(beta(a,b)==B);
rd2_1.show()
This is a lot, but again we can use eq2,eq3
to simplify.
rd2_2=rd2_1._sympy_().subs(eq2.op[0],eq2.op[1]).subs(eq3.op[0],eq3.op[1]);
Some more simplification with sympy
, and study the denominator and numerator separately.
rd2_numer, rd2_denom=sympy.fraction(rd2_2.together())
The denominator.
rd2_denom1=rd2_denom.simplify()._sage_();
rd2_denom1.show()
We want the 2nd direvative to be positive when $b>a>1$, so we can ingore the first 3 terms, which are positive.
rd2_denom2=rd2_denom1.op[-1];
rd2_denom2.show()
The numerator.
rd2_numer1=rd2_numer.simplify()._sage_();
rd2_numer1.show()
Put the numerator and denominator back and separte them again, which actually simplifies again.
numer3,denom3=sympy.fraction((rd2_numer1/rd2_denom2)._sympy_().together())
The denominator.
denom3.expand().collect(x1)._sage_().show()
This is $>0$ if $x_1 > m(a,b)= (a-1)/(a+b-2)$, which is our assumption. So the denominator does not matter.
Factor the numerator
numer4=numer3.factor()._sage_();
numer4.show()
If we restrict that $x<x_1$, then the last 4 terms are positive. So we can drop them. We only need to show the 1st term is positve.
numer5 = numer4.op[0];
numer5.show()
numer6=numer5._sympy_().collect(x).collect(x1).collect(a+b-2);
numer6._sage_().show()
This is $>0$ if $$ x+x_1>\frac{2 a +2 }{a+b-2} $$ and I mentioned in my earlier post, this is very simple and is left as an exercise.