#!/usr/bin/env python # coding: utf-8 # # Maximum entropy principle # Florent Leclercq,
# Imperial Centre for Inference and Cosmology, Imperial College London,
# florent.leclercq@polytechnique.org # In[1]: from scipy.optimize import fsolve from math import log, pow import numpy as np import matplotlib.pyplot as plt # ## Dice example # The constraints are $\sum_{n=1}^{6} n p_n = 4$ (contraint on the mean) and $\sum_{n=1}^{6} p_n = 1$ (normalization constraint). The Lagrangian is # \begin{equation} # \mathcal{L}[\{p_n\},\lambda,\mu] = - \sum_{n=1}^{6} p_n \ln p_n - \lambda \left( \sum_{n=1}^{6} n p_n - 4 \right) - \mu \left( \sum_{n=1}^{6} p_n - 1 \right). # \end{equation} # In[2]: mean=4 # $\dfrac{\partial \mathcal{L}}{\partial p_n} =0$ fixes $p_n = \dfrac{\mathrm{e}^{-\lambda n}}{Z} = \dfrac{x^{-n}}{Z}$ (we define $x \equiv \mathrm{e}^\lambda$). # In[3]: def p1(x): return pow(x,-1)/Z(x) def p2(x): return pow(x,-2)/Z(x) def p3(x): return pow(x,-3)/Z(x) def p4(x): return pow(x,-4)/Z(x) def p5(x): return pow(x,-5)/Z(x) def p6(x): return pow(x,-6)/Z(x) # The normalization constraint $\sum_{n=1}^{6} p_n = 1$ fixes # \begin{equation} # Z = \sum_{n=1}^{6} \mathrm{e}^{-\lambda n} = \dfrac{1-\mathrm{e}^{-6\lambda}}{\mathrm{e}^\lambda-1} = \dfrac{1-x^{-6}}{x-1}. # \end{equation} # In[4]: def Z(x): return (1-pow(x,-6))/(x-1) # The constraint on the mean is obtained by noting that # \begin{equation} # - \frac{\mathrm{d} \ln Z}{\mathrm{d} \lambda} = -\frac{1}{Z} \frac{\mathrm{d}Z}{\mathrm{d}\lambda} = \sum_{n=1}^6 n \frac{\mathrm{e}^{-\lambda n}}{Z} = \sum_{n=1}^6 n \, p_n = 4. # \end{equation} # This gives an equation for $\lambda$: $\mathrm{e}^\lambda/(\mathrm{e}^\lambda-1) - 6/(\mathrm{e}^{6\lambda}-1)= 4$. # In[5]: # we now solve the equation giving x=exp(lambda) def f(x): return x/(x-1) - 6/(pow(x,6)-1) - mean # This is -dlnZ/dZ-mean, which should be 0 x0=fsolve(f,2)[0] x0 # In[6]: # using the solution for x, we have the probability assignment: pn = (p1(x0), p2(x0), p3(x0), p4(x0), p5(x0), p6(x0)) pn # In[7]: plt.bar(np.arange(1,7),1/6.,label="fair dice") plt.bar(np.arange(1,7),pn,label="loaded dice",alpha=0.8) plt.xlabel("face") plt.ylabel("probability") plt.legend() # In[8]: # check normalization constraint p1(x0)+p2(x0)+p3(x0)+p4(x0)+p5(x0)+p6(x0) # In[9]: # check mean constraint 1*p1(x0)+2*p2(x0)+3*p3(x0)+4*p4(x0)+5*p5(x0)+6*p6(x0) # ## Cosmic web example # The cosmic web is described by four possible structures ($\theta_0=$ void, $\theta_1=$ sheet, $\theta_2=$ filament, and $\theta_3=$ cluster. We are looking for the prior probabilities $p_n$ ($n = 0, ..., 3$) that one should assign to each of these structures. Let us assume that we have measured in astronomical observations the (average) volume of structures: # In[10]: # Volume of the different structures (arbitrary normalization) # (based on numbers given in table II in Leclercq et al. 2015a, arXiv:1502.02690) V0 = 60 V1 = 20 V2 = 8 V3 = 1 # The cosmological principle states that there cannot be cosmological structures at arbitrary large scales (the "End of Greatness"); let us say that this imposes the average volume of a random cosmic web element to be: # In[11]: # The average volume of a random cosmic web structure V = 30 # Just on the basis of these observations, the maximum entropy principle fixes the new prior probabilities $p_n$ that one should use. They are given in canonical notations as $p_n = \mathrm{e}^{-\beta V_n}/Z$ with $Z=\sum_n \mathrm{e}^{-\beta V_n}$. # In[12]: # x=exp(-beta) in the usual thermodynamic notations def Z(x): return pow(x,V0)+pow(x,V1)+pow(x,V2)+pow(x,V3) def p0(x): return pow(x,V0)/Z(x) def p1(x): return pow(x,V1)/Z(x) def p2(x): return pow(x,V2)/Z(x) def p3(x): return pow(x,V3)/Z(x) def dlnZdx(x): return p0(x)*V0+p1(x)*V1+p2(x)*V2+p3(x)*V3 # Solving $\left\langle V \right\rangle = -\partial Z/\partial \beta = \bar{V}$ fixes $\beta$: # In[13]: def f(x): return dlnZdx(x)-V x0=fsolve(f,0.9)[0] x0 # The solution is therefore: # In[14]: P0=p0(x0); P1=p1(x0); P2=p2(x0); P3=p3(x0) P0,P1,P2,P3 # In[15]: # check normalization constraint P0+P1+P2+P3 # In[16]: # check average volume constraint P0*V0+P1*V1+P2*V2+P3*V3