{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# iPEPS contraction for computing $\\ln Z$ of the $2-$D ferromagnetic Ising model" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## $Z$ as contraction of PEPS\n", "The partition function of $2-$D Ising model can be written as\n", "$$Z=\\sum_\\mathbf{s}\\prod_{ij}e^{\\beta J_{ij}s_is_j}=\\sum_\\mathbf{s}\\prod_i^\\circ\\sqrt{A_i}.$$ Where $\\prod_i^\\circ$ denotes tensor contraction of all the $A_i$ tensors, each of which is a tensor given by $$A_i = I_i\\prod_{j\\in\\partial i}\\sqrt{B_{ij}},$$ where $I$ is a identity tensor with order equals to the degree of node $i$, and $B_{ij}$ defines a Boltzmann matrix with $$B_{ij}=\\left[\\begin{array}{l}e^{\\beta J_{ij}}& e^{-\\beta J_{ij}} \\\\ e^{-\\beta J_{ij}}& e^{\\beta J_{ij}}\\end{array}\\right].$$ $\\sqrt{B}$ indicates square root of matrix $B$, yileding $\\sqrt{B}\\times \\sqrt{B} = B$. For the ferromagnetic model, every $B$ matrix and $A$ tensor are identical, the system has a rotational invariance." ] }, { "cell_type": "code", "execution_count": 130, "metadata": {}, "outputs": [], "source": [ "import torch\n", "from scipy.linalg import sqrtm\n", "import numpy as np\n", "import sys,math\n", "\n", "mydevice = torch.device('cpu')\n", "mydtype=torch.float64\n", "beta=0.5\n", "def get_A(beta=0.5):\n", " b=np.exp(beta)\n", " B=torch.tensor(sqrtm(np.array([[b,1/b],[1/b,b]])),dtype=mydtype,device=mydevice) # the Boltzmann matrix\n", " I=torch.zeros([2,2,2,2],dtype=mydtype) # the identity matrix defined on each site\n", " I[0,0,0,0]=1\n", " I[1,1,1,1]=1\n", " Im=I.clone()\n", " Im[1,1,1,1]=-1\n", " A=torch.einsum(\"ij,ab,cd,xy,jbdy->iacx\",B,B,B,B,I) #\n", " Am= torch.einsum(\"ij,ab,cd,xy,jbdy->iacx\",B,B,B,B,Im) # this will be used for computing magnetization\n", " return A,Am" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Onsager solution\n", "What we are going to compare with is the Onsager solution, with $\\ln Z$, critical temperature $\\beta_c$, and the spontaneous magnetization are given as\n", "\\begin{align} \\ln Z&=\\ln 2 +\\frac{1}{8\\pi^2}\\int_0^{2\\pi}d\\theta_1\\int_0^{2\\pi}d\\theta_2\\ln\\left[ \\cosh^2(2\\beta)-\\sinh(2\\beta)\\cos(\\theta_1)-\\sinh(2\\beta)\\cos(\\theta_2) \\right]\\\\\n", "\\beta_c&=\\frac{\\ln (1+\\sqrt{2})}{2},\\\\\n", "m_{\\beta \\gt \\beta_c}&=\\left[ 1-\\sinh^{-4}(2\\beta) \\right]^{\\frac{1}{8}}.\n", "\\end{align}\n", "\n" ] }, { "cell_type": "code", "execution_count": 161, "metadata": {}, "outputs": [], "source": [ "def m_exact(beta):\n", " if(beta>0.5*math.log(1+math.sqrt(2))):\n", " return math.pow((1- math.pow(math.sinh(2*beta),-4)),1/8 )\n", " else:\n", " return 0" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## CTMRG for rotational and translational symmetric iPEPS\n", "The Corner Transfer Matrix RG method for contracting iPEPS takes care of a corner matrix $C$ and an edge matrix $E$, with $Z$ finally expressed as\n", "$$ Z=\\begin{array}{c}C&-&E&-&C\\\\|&&|&&|\\\\E&-&A&-&E\\\\|&&|&&|\\\\C&-&E&-&C\\end{array}$$\n", "The $C$ is updated by \n", "$$ \\begin{array}{c}C&-&E&-\\\\|&&|\\\\E&-&A&-\\\\|&&|&\\\\\\end{array}\\,\\,\\,\\,\\,\\longrightarrow\\begin{array}{c}\\widehat C&=\\\\\\|&\\\\ \\end{array}\\,\\,\\,\\,\\,\\longrightarrow \\begin{array}{c}C&-&U&=\\\\|&&&\\\\U^{\\dagger}&&&\\\\\\|&&& \\end{array}$$\n", "And we can see that after one step of update, $C$ is actually the diagonal matrix containing truncated eigenvalues of $\\widehat C$, and $U$ contains conrreponding eigenvectors.\n", "The edge tensor $E$ is updated as\n", "$$ \\begin{array}{c}|&&|\\\\E&-&A&-\\\\|&&| \\end{array}\\,\\,\\,\\,\\,\\longrightarrow \\begin{array}{c} \\|\\\\ \\widehat E&-\\\\ \\| \\end{array} \\,\\,\\,\\,\\,\\longrightarrow \\,\\,\\,\\,\\, \\begin{array}{c} \\|\\\\ U \\\\ |\\\\U^{\\dagger}\\\\ \\| \\\\ \\widehat E&-\\\\\\|\\\\U\\\\|\\\\U^{\\dagger}\\\\ \\|\\end{array} \\longrightarrow \\,\\,\\,\\,\\, \\begin{array}{c} \\|\\\\ U \\\\ |\\\\ E&-\\\\|\\\\U^{\\dagger}\\\\\\|\\end{array}$$ \n", "\n", "For the detailed einsum rules for updates corner matrix $C$, I have used in the code that\n", "$$ \\begin{array}{c}C&-_j&E&-_k\\\\|_i&&|_l\\\\E&-_n&A&-_a\\\\|_m&&|_b&\\\\\\end{array}$$\n", "\n", "For update of $E$, \n", "$$ \\begin{array}{c}|_j&&|_l\\\\E&-_k&A&-_m\\\\|_i&&|_n \\end{array}$$\n", "\n", "And for finall contractions \n", "$$ Z=\\begin{array}{c}C&-_b&E&-_d&C\\\\|_a&&|_c&&|_e\\\\E&-_g&A&-_i&E\\\\|_f&&|_h&&|_j\\\\C&-_k&E&-_l&C\\end{array}$$\n", "Also be very careful about the order of the original indices of bonds when two bonds are merged into a singer boarder bond.\n" ] }, { "cell_type": "code", "execution_count": 173, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "beta=0.48,beta_C=0.440687\n", "m_ctm = -0.877523 m_exact=0.877523\n" ] } ], "source": [ "beta=0.48\n", "A,Am = get_A(beta)\n", "iter_max = 100\n", "tol = 1.0e-10\n", "Dmax = 10\n", "C = B@torch.eye(2,dtype=mydtype)@B # initial C\n", "I3=torch.zeros([2,2,2],dtype=mydtype) \n", "I3[0,0,0]=1\n", "I3[1,1,1]=1\n", "E = torch.einsum(\"ij,ab,cd,jbd->iac\",B,B,B,I3) # initial E\n", "C = torch.randn(2,2,dtype=mydtype)\n", "E = torch.randn(2,2,2,dtype=mydtype)\n", "err=1.0\n", "for iter in range(iter_max):\n", " #update C\n", " Chat = torch.einsum(\"ij,jkl,min,nlab->bmak\",C,E,E,A).contiguous().view([E.shape[0]*A.shape[3],E.shape[1]*A.shape[2]])\n", " [U,s,V]=torch.svd(Chat)\n", " if(s.numel()>Dmax):\n", " s=s[:Dmax]\n", " U=U[:,:Dmax]\n", " Cnew = torch.diag(s)\n", " Cnew = Cnew/Cnew.norm()\n", " if(C.shape == Cnew.shape):\n", " err=(Cnew-C).norm()\n", " #sys.stdout.write(\"#%d err=%.3g \\n\"%(iter,err))\n", " if(errniljm\",E,A).contiguous().view(E.shape[0]*A.shape[3],E.shape[1]*A.shape[1],A.shape[2])\n", " E = torch.einsum(\"ijk,jl,im->mlk\",E,U,U)\n", " E = E/E.norm()\n", "Z=torch.einsum(\"ab,bdc,de,fag,hgci,eji,kf,lkh,jl\",C,E,C,E,A,E,C,E,C)\n", "Zm=torch.einsum(\"ab,bdc,de,fag,hgci,eji,kf,lkh,jl\",C,E,C,E,Am,E,C,E,C)\n", "\n", "print(\"beta=%g,beta_C=%g\"%(beta,0.5*math.log(1+math.sqrt(2))))\n", "print(\"m_ctm = %g\"%(Zm/Z).item(),\"m_exact=%g\"% m_exact(beta))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "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.6.5" } }, "nbformat": 4, "nbformat_minor": 2 }