{
"cells": [
{
"cell_type": "markdown",
"id": "fbf7e57b-99e8-4d77-a076-e4fb6187198d",
"metadata": {
"raw_mimetype": "text/restructuredtext"
},
"source": [
"(tensor-network-1d)=\n",
"\n",
"# 1D Algorithms\n",
"\n",
"Although `quimb.tensor` aims to be an interactive and general\n",
"base for arbitrary tensor networks, it also has fast\n",
"implementations of the following:\n",
"\n",
"Static:\n",
"\n",
"- 1-site {class}`~quimb.tensor.tn1d.dmrg.DMRG1` (OBC and PBC)\n",
"- 2-site {class}`~quimb.tensor.tn1d.dmrg.DMRG2` (OBC and PBC)\n",
"- 1-site {class}`~quimb.tensor.tn1d.dmrg.DMRGX`\n",
"\n",
"Time Evolving:\n",
"\n",
"- {class}`~quimb.tensor.tn1d.tebd.TEBD`\n",
"\n",
"Two site DMRGX and TDVP slot into the same framework and should be\n",
"easy to implement. All of these are based on 1D tensor networks, the\n",
"primary representation of which is the *matrix product state*.\n",
"\n",
"## Matrix Product States\n",
"\n",
"The basic constructor for MPS is {class}`~quimb.tensor.tn1d.core.MatrixProductState`.\n",
"This is a subclass of {class}`~quimb.tensor.tensor_core.TensorNetwork`,\n",
"with a special tagging scheme (`MPS.site_tag_id`) and special index\n",
"naming sceme (`MPS.site_ind_id`).\n",
"It is also possible to instantiate a MPS directly from a dense vector using\n",
"{meth}`~quimb.tensor.tn1d.core.MatrixProductState.from_dense`, though\n",
"this is obviously not efficient for many sites.\n",
"\n",
"In the following, we just generate a random MPS, and demonstrate some basic functionality."
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "a09fbeac-937c-4a10-a45f-10ef039501aa",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"%config InlineBackend.figure_formats = ['svg']\n",
"import quimb.tensor as qtn"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "5605fc1f-ec6f-4a3c-8ed3-a9beba7b2f27",
"metadata": {
"tags": []
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Site tags: 'I{}', site inds: 'k{}'\n"
]
}
],
"source": [
"p = qtn.MPS_rand_state(L=20, bond_dim=50)\n",
"print(f\"Site tags: '{p.site_tag_id}', site inds: '{p.site_ind_id}'\")"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "15a60b40-e9fd-4977-abbe-c20f45ffae2e",
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"text/html": [
"MatrixProductState(tensors=20, indices=39, L=20, max_bond=50)
Tensor(shape=(50, 2), inds=[_5f4cf2AAAAB, k0], tags={I0}),
backend=numpy, dtype=float64, data=array([[ 0.11497926, -0.03301575],\n",
" [ 0.14287527, 0.09528585],\n",
" [ 0.00901042, 0.2894635 ],\n",
" [ 0.16597057, -0.21087768],\n",
" [ 0.06840515, 0.12352524],\n",
" [-0.22859016, -0.17975555],\n",
" [ 0.05865437, -0.06229958],\n",
" [-0.22543584, 0.3537363 ],\n",
" [-0.06192183, 0.28997241],\n",
" [ 0.26098978, 0.22142932],\n",
" [-0.0009746 , 0.27116365],\n",
" [-0.15374373, 0.15679591],\n",
" [-0.20771046, -0.08438128],\n",
" [-0.25183218, 0.09779763],\n",
" [ 0.03309358, 0.25402115],\n",
" [ 0.1227192 , -0.03237239],\n",
" [ 0.02314386, 0.02195231],\n",
" [-0.14617185, 0.06040895],\n",
" [ 0.17080921, 0.20391648],\n",
" [-0.00561205, 0.0351818 ],\n",
" [-0.03369533, 0.00391024],\n",
" [-0.09223657, -0.26126876],\n",
" [ 0.14816727, 0.02891876],\n",
" [-0.3639576 , 0.20622844],\n",
" [-0.23466335, -0.14550278],\n",
" [ 0.06237061, 0.05168888],\n",
" [ 0.26869372, 0.10526992],\n",
" [ 0.21123979, 0.01902058],\n",
" [ 0.23698972, -0.10852923],\n",
" [ 0.07679655, -0.18927693],\n",
" [ 0.06330614, -0.28509499],\n",
" [ 0.17135434, 0.18174649],\n",
" [-0.11352344, 0.16434296],\n",
" [ 0.01546874, -0.07752756],\n",
" [ 0.26005355, 0.15271884],\n",
" [-0.32407436, -0.21623951],\n",
" [ 0.05711339, 0.05123744],\n",
" [-0.10898201, -0.09929992],\n",
" [-0.11903359, -0.07486332],\n",
" [-0.02304992, 0.33368523],\n",
" [ 0.17590111, 0.11170404],\n",
" [-0.29728279, -0.3769343 ],\n",
" [ 0.05783727, -0.12450645],\n",
" [-0.09915666, 0.18961208],\n",
" [ 0.17556912, -0.140988 ],\n",
" [ 0.15249451, 0.13108079],\n",
" [ 0.3249881 , -0.12510249],\n",
" [ 0.02966852, -0.14102299],\n",
" [ 0.01672216, -0.31966811],\n",
" [-0.15577892, -0.25972279]])Tensor(shape=(50, 50, 2), inds=[_5f4cf2AAAAB, _5f4cf2AAAAC, k1], tags={I1}),
backend=numpy, dtype=float64, data=...Tensor(shape=(50, 50, 2), inds=[_5f4cf2AAAAC, _5f4cf2AAAAD, k2], tags={I2}),
backend=numpy, dtype=float64, data=...Tensor(shape=(50, 50, 2), inds=[_5f4cf2AAAAD, _5f4cf2AAAAE, k3], tags={I3}),
backend=numpy, dtype=float64, data=...Tensor(shape=(50, 50, 2), inds=[_5f4cf2AAAAE, _5f4cf2AAAAF, k4], tags={I4}),
backend=numpy, dtype=float64, data=...Tensor(shape=(50, 50, 2), inds=[_5f4cf2AAAAF, _5f4cf2AAAAG, k5], tags={I5}),
backend=numpy, dtype=float64, data=...Tensor(shape=(50, 50, 2), inds=[_5f4cf2AAAAG, _5f4cf2AAAAH, k6], tags={I6}),
backend=numpy, dtype=float64, data=...Tensor(shape=(50, 50, 2), inds=[_5f4cf2AAAAH, _5f4cf2AAAAI, k7], tags={I7}),
backend=numpy, dtype=float64, data=...Tensor(shape=(50, 50, 2), inds=[_5f4cf2AAAAI, _5f4cf2AAAAJ, k8], tags={I8}),
backend=numpy, dtype=float64, data=...Tensor(shape=(50, 50, 2), inds=[_5f4cf2AAAAJ, _5f4cf2AAAAK, k9], tags={I9}),
backend=numpy, dtype=float64, data=...Tensor(shape=(50, 50, 2), inds=[_5f4cf2AAAAK, _5f4cf2AAAAL, k10], tags={I10}),
backend=numpy, dtype=float64, data=...Tensor(shape=(50, 50, 2), inds=[_5f4cf2AAAAL, _5f4cf2AAAAM, k11], tags={I11}),
backend=numpy, dtype=float64, data=...Tensor(shape=(50, 50, 2), inds=[_5f4cf2AAAAM, _5f4cf2AAAAN, k12], tags={I12}),
backend=numpy, dtype=float64, data=...Tensor(shape=(50, 50, 2), inds=[_5f4cf2AAAAN, _5f4cf2AAAAO, k13], tags={I13}),
backend=numpy, dtype=float64, data=...Tensor(shape=(50, 50, 2), inds=[_5f4cf2AAAAO, _5f4cf2AAAAP, k14], tags={I14}),
backend=numpy, dtype=float64, data=...Tensor(shape=(50, 50, 2), inds=[_5f4cf2AAAAP, _5f4cf2AAAAQ, k15], tags={I15}),
backend=numpy, dtype=float64, data=...Tensor(shape=(50, 50, 2), inds=[_5f4cf2AAAAQ, _5f4cf2AAAAR, k16], tags={I16}),
backend=numpy, dtype=float64, data=...Tensor(shape=(50, 50, 2), inds=[_5f4cf2AAAAR, _5f4cf2AAAAS, k17], tags={I17}),
backend=numpy, dtype=float64, data=...Tensor(shape=(50, 50, 2), inds=[_5f4cf2AAAAS, _5f4cf2AAAAT, k18], tags={I18}),
backend=numpy, dtype=float64, data=...Tensor(shape=(50, 2), inds=[_5f4cf2AAAAT, k19], tags={I19}),
backend=numpy, dtype=float64, data=array([[-0.01865475, 0.01300301],\n",
" [ 0.02495254, 0.00097399],\n",
" [ 0.00848525, -0.00144896],\n",
" [-0.00096869, -0.03214158],\n",
" [ 0.03487788, 0.00254655],\n",
" [-0.00812462, 0.00177065],\n",
" [-0.03328353, 0.02973276],\n",
" [ 0.00054345, 0.03585691],\n",
" [ 0.01457306, 0.00283571],\n",
" [ 0.01791563, 0.00535112],\n",
" [ 0.01077653, -0.01792025],\n",
" [-0.03232937, -0.01825245],\n",
" [ 0.0166193 , -0.00704982],\n",
" [ 0.00776656, -0.00770383],\n",
" [ 0.01284421, -0.03308349],\n",
" [ 0.02487397, 0.03179995],\n",
" [ 0.0362839 , -0.00196856],\n",
" [-0.00203145, -0.01783675],\n",
" [ 0.02933126, 0.00379016],\n",
" [ 0.01829577, -0.00144067],\n",
" [ 0.00951322, 0.00955651],\n",
" [-0.02108138, 0.0173931 ],\n",
" [ 0.00055177, 0.03024101],\n",
" [-0.0208759 , 0.0027221 ],\n",
" [-0.01316994, 0.02733795],\n",
" [ 0.00213805, 0.01541775],\n",
" [ 0.00456172, -0.00833056],\n",
" [-0.00757534, -0.00348482],\n",
" [ 0.01824206, -0.00121908],\n",
" [-0.02637555, -0.00039397],\n",
" [-0.02000728, -0.00591133],\n",
" [ 0.00689531, 0.00956602],\n",
" [ 0.02826997, 0.00185794],\n",
" [-0.00230382, -0.01326473],\n",
" [ 0.01851884, -0.00885802],\n",
" [ 0.03197927, 0.01166369],\n",
" [-0.0113239 , -0.01783043],\n",
" [ 0.02129273, 0.01501489],\n",
" [ 0.00314024, 0.01877841],\n",
" [ 0.0119419 , -0.00188692],\n",
" [-0.01856547, 0.00473795],\n",
" [-0.01303102, 0.01257095],\n",
" [-0.01253511, -0.01038849],\n",
" [-0.00914257, -0.014063 ],\n",
" [-0.01275447, 0.01772058],\n",
" [ 0.01692373, -0.01584735],\n",
" [-0.01224494, 0.00804811],\n",
" [-0.00668428, -0.01034734],\n",
" [-0.01417805, -0.01249803],\n",
" [-0.00142995, -0.01114324]]) "
],
"text/plain": [
"MatrixProductState(tensors=20, indices=39, L=20, max_bond=50)"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# in a notebook we can explore a colorized representation:\n",
"p"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "99ba3a10-2090-48d2-bfbf-759a88332d99",
"metadata": {
"tags": []
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 \n",
"●──●──●──●──●──●──●──●──●──●──●──●──●──●──●──●──●──●──●──●\n",
"│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │\n"
]
}
],
"source": [
"p.show() # 1D tensor networks also have a ascii ``show`` method"
]
},
{
"cell_type": "markdown",
"id": "a76f8b8a-d7b6-4b96-9742-b4a9936f452f",
"metadata": {},
"source": [
"We can then __canonicalize__ the MPS:"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "e3a5c98d-e02b-4db8-a586-4c89c3c8cf46",
"metadata": {
"tags": []
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" 2 4 8 16 32 50 50 50 50 50 50 50 50 50 50 50 50 50 50 \n",
">─>─>─>──>──>──>──>──>──>──>──>──>──>──>──>──>──>──>──●\n",
"│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │\n"
]
}
],
"source": [
"p.left_canonize()\n",
"p.show()"
]
},
{
"cell_type": "markdown",
"id": "69d9afea-8a02-4d53-afcc-2867c065a3b6",
"metadata": {},
"source": [
"And we can compute the inner product as:"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "238abe86-fda6-49bd-95e6-b6167feac56e",
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"text/plain": [
"np.float64(0.9999999999999998)"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"p.H @ p"
]
},
{
"cell_type": "markdown",
"id": "dc75ccd4-0288-4598-9411-024ec9fb71e8",
"metadata": {},
"source": [
"This relies on them sharing the same physical indices, ``site_ind_id``,\n",
"which the conjugated copy ``p.H`` naturally does.\n",
"\n",
"Like any TN, we can __graph__ the overlap for example, and make use of the\n",
"site tags to color it:"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "cbb444e7-7232-44b6-9987-55ac8c361c29",
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"image/svg+xml": [
""
],
"text/plain": [
""
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"(p.H & p).draw(color=[f\"I{i}\" for i in range(20)], layout=\"sfdp\")"
]
},
{
"cell_type": "markdown",
"id": "e5af2481-8ff8-45ca-9041-68bed470e193",
"metadata": {
"raw_mimetype": "text/restructuredtext"
},
"source": [
"I.e. we used the fact that 1D tensor networks are tagged with the structure `\"I{}\"`\n",
"denoting their sites. See the {ref}`examples` for how to fix the positions of tensors when drawing them.\n",
"\n",
"We can also **add** MPS, and **multiply/divide** them by scalars:"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "b4b8d8d0-85dc-4e78-b865-43733f8a2af7",
"metadata": {
"tags": []
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" 4 8 16 32 64 100 100 100 100 100 100 100 100 100 100 100 100 100 100 \n",
"●─●─●──●──●──●━━━●━━━●━━━●━━━●━━━●━━━●━━━●━━━●━━━●━━━●━━━●━━━●━━━●━━━●\n",
"│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │\n"
]
}
],
"source": [
"p2 = (p + p) / 2\n",
"p2.show()"
]
},
{
"cell_type": "markdown",
"id": "7d7dd30d-0cd4-4aab-866d-c49ba7260cbc",
"metadata": {},
"source": [
"Which doubles the bond dimension, as expected, but should still be normalized:"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "a6421495-74b6-4970-82a6-c7d36b506c7a",
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"text/plain": [
"np.float64(0.9999999999999998)"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"p2.H @ p2"
]
},
{
"cell_type": "markdown",
"id": "a239c40d-f76e-491d-89e4-6b376464b0ab",
"metadata": {},
"source": [
"Because the MPS is the addition of two identical states, it should also __compress__ right back down:"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "9361b405-9cad-4d5a-93db-4c8998525965",
"metadata": {
"tags": []
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" 2 4 8 16 32 50 50 50 50 50 50 50 50 50 32 16 8 4 2 \n",
">─>─>─>──>──>──>──>──>──>──●──<──<──<──<──<──<─<─<─<\n",
"│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │\n"
]
}
],
"source": [
"p2.compress(form=10)\n",
"p2.show()"
]
},
{
"cell_type": "markdown",
"id": "7a45b76a-71f8-4a55-aa92-a83b73bc6e71",
"metadata": {},
"source": [
"Where we have also set the __orthogonality center__ at the site 10.\n",
"\n",
"When tensor networks are imbued with a ``structure``, they\n",
"can be indexed with integers and slices, which automatically get\n",
"converted using ``TN.site_tag_id``:"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "4d71a98c-2ecc-4305-abe9-efbefac78a62",
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"text/html": [
"Tensor(shape=(50, 50, 2), inds=[_5f4cf2AAAAK, _5f4cf2AAAAL, k10], tags={I10}),
backend=numpy, dtype=float64, data=... "
],
"text/plain": [
"Tensor(shape=(50, 50, 2), inds=('_5f4cf2AAAAK', '_5f4cf2AAAAL', 'k10'), tags=oset(['I10']))"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"p2[10] # get the tensor(s) with tag 'I10'."
]
},
{
"cell_type": "markdown",
"id": "e0698a3d-0895-42ba-a246-a5ece63e2ca3",
"metadata": {},
"source": [
"Note the tensor has matching physical index ``'k10'``.\n",
"\n",
"This tensor is the orthogonality center so:\n",
"\n",
" ─>─>─●─<─<─ ╭─●─╮\n",
" ... │ │ │ │ │ ... = │ │ │\n",
" ─>─>─●─<─<─ ╰─●─╯\n",
" i=10 i=10\n",
"\n",
"should compute the normalization of the *whole* state:"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "e8f7f02b-ce1c-46cf-b598-1889eb3f58e0",
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"text/plain": [
"1.0000000000000036"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"p2[10].H @ p2[10] # all indices match -> inner product"
]
},
{
"cell_type": "markdown",
"id": "8f4cec48-edf9-4c49-a272-f2f34f468f4d",
"metadata": {},
"source": [
"Or equivalently:"
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "02f1dc94-2b90-4e5b-8de1-b96798c17d97",
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"text/plain": [
"np.float64(1.0000000000000018)"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"p2[10].norm()"
]
},
{
"cell_type": "markdown",
"id": "de2bf4e3-881a-4faa-8f2b-1915ddfabe1c",
"metadata": {},
"source": [
"If two tensor networks with the same ``structure`` are combined, it is propagated.\n",
"For example ``(p2.H & p2)`` can still be sliced.\n",
"\n",
"Since the MPS is in canonical form, left and right pieces of the overlap\n",
"should form the identity. The following forms a TN of the inner product,\n",
"selects the *2* tensors corresponding to the last site (``-1``), contracts them,\n",
"then gets the underlying data:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1fdc3b10-0586-4d15-a544-362d3ce1bbeb",
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"text/plain": [
"array([[1., 0.],\n",
" [0., 1.]])"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# should be close to the identity\n",
"((p2.H & p2).select(-1) ^ all).data.round(12)"
]
},
{
"cell_type": "markdown",
"id": "73266c89-b80b-4ada-939c-2b16b96146bf",
"metadata": {
"raw_mimetype": "text/restructuredtext"
},
"source": [
"Various builtin quantities are available to compute too:\n",
"\n",
"- {meth}`~quimb.tensor.tn1d.core.MatrixProductState.entropy`\n",
"- {meth}`~quimb.tensor.tn1d.core.MatrixProductState.schmidt_gap`\n",
"- {meth}`~quimb.tensor.tn1d.core.MatrixProductState.magnetization`\n",
"- {meth}`~quimb.tensor.tn1d.core.TensorNetwork1DVector.correlation`\n",
"- {meth}`~quimb.tensor.tn1d.core.MatrixProductState.logneg_subsys`\n",
"\n",
"and other non-trivial quantities such as the mutual information\n",
"can be easily calculated using a combination of -\n",
"{meth}`~quimb.tensor.tn1d.core.MatrixProductState.partial_trace_compress`\n",
"and {func}`~quimb.approx_spectral_function` (see {ref}`Examples`).\n",
"Finally, many quantities can be computed using local 'gates' see the section\n",
"{ref}`gating`."
]
},
{
"cell_type": "markdown",
"id": "e7daa1f6-29d2-4158-83c8-3d73356376b6",
"metadata": {
"raw_mimetype": "text/restructuredtext"
},
"source": [
"## Matrix Product Operators\n",
"\n",
"The raw MPO class is {class}`~quimb.tensor.tn1d.core.MatrixProductOperator`,\n",
"which shares many features with {class}`~quimb.tensor.tn1d.core.MatrixProductState`,\n",
"but has both a `MPO.upper_ind_id` and a `MPO.lower_ind_id`.\n",
"\n",
"Here we generate a random hermitian MPO and form a 'overlap' network with our MPS:"
]
},
{
"cell_type": "code",
"execution_count": 15,
"id": "60c7c66b-4b20-41b2-89ba-5866c26556c6",
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"image/svg+xml": [
""
],
"text/plain": [
""
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"A = qtn.MPO_rand_herm(20, bond_dim=7, tags=[\"HAM\"])\n",
"pH = p.H\n",
"\n",
"# This inplace modifies the indices of each to form overlap\n",
"p.align_(A, pH)\n",
"\n",
"(pH & A & p).draw(color=\"HAM\", iterations=20, layout=\"sfdp\")"
]
},
{
"cell_type": "markdown",
"id": "9f3b016f-343c-4f6c-b37e-9ee8085f1ee9",
"metadata": {},
"source": [
"Compute the actual contraction (``...`` means contract everything, but use the structure if possible):"
]
},
{
"cell_type": "code",
"execution_count": 16,
"id": "3d026049-ae22-4d22-ba86-f7a97051a5ff",
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"text/plain": [
"4.956509909557158e-07"
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"(pH & A & p) ^ ..."
]
},
{
"cell_type": "markdown",
"id": "fa0d2290-4d72-48e8-bb7a-fff2b3be203e",
"metadata": {
"raw_mimetype": "text/restructuredtext"
},
"source": [
"## Building Hamiltonians\n",
"\n",
"There are various built-in MPO hamiltoanians:\n",
"\n",
"- {class}`~quimb.tensor.tensor_builder.MPO_ham_heis`\n",
"- {class}`~quimb.tensor.tensor_builder.MPO_ham_ising`\n",
"- {class}`~quimb.tensor.tensor_builder.MPO_ham_XY`\n",
"- {class}`~quimb.tensor.tensor_builder.MPO_ham_mbl`\n",
"- ...\n",
"\n",
"These all accept a `cyclic` argument to enable periodic boundary\n",
"conditions (PBC), and a `S` argument to set the size of spin.\n",
"\n",
"For generating other spin Hamiltonians see\n",
"{class}`~quimb.tensor.tensor_builder.SpinHam1D`, or consider using the raw\n",
"constructor of {class}`~quimb.tensor.tn1d.core.MatrixProductOperator`.\n",
"\n",
"## Quick DMRG2 Intro\n",
"\n",
"First we build a Hamiltonian term by term (though we could just use {class}`~quimb.tensor.tensor_builder.MPO_ham_heis`):"
]
},
{
"cell_type": "code",
"execution_count": 17,
"id": "e780c69c-1b19-4e3d-81ed-f4eb3495aca4",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"builder = qtn.SpinHam1D(S=1)\n",
"builder += 1 / 2, \"+\", \"-\"\n",
"builder += 1 / 2, \"-\", \"+\"\n",
"builder += 1, \"Z\", \"Z\"\n",
"H = builder.build_mpo(L=100)"
]
},
{
"cell_type": "markdown",
"id": "107900a3-fdc6-49c9-8f9d-bcd651749285",
"metadata": {
"raw_mimetype": "text/restructuredtext"
},
"source": [
"Then we construct the 2-site DMRG object ({class}`~quimb.tensor.tn1d.dmrg.DMRG2`), with the Hamiltonian MPO and a default sequence of maximum bond dimensions and a bond compression cutoff:"
]
},
{
"cell_type": "code",
"execution_count": 18,
"id": "3c4d4e39-611b-4a0b-8d2c-e12e21cd0bb7",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"dmrg = qtn.DMRG2(H, bond_dims=[10, 20, 100, 100, 200], cutoffs=1e-10)"
]
},
{
"cell_type": "markdown",
"id": "15169e22-6b6c-4562-ae44-96394d499eae",
"metadata": {},
"source": [
"The ``DMRG`` object will automatically detect OBC/PBC. Now we can solve to a certain absolute energy tolerance, showing progress and a schematic of the final state:"
]
},
{
"cell_type": "code",
"execution_count": 19,
"id": "badbf285-7f94-46d1-bb1b-abfd9f2f201e",
"metadata": {
"tags": []
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"1, R, max_bond=(10/10), cutoff:1e-10\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"100%|##########################################| 99/99 [00:00<00:00, 157.48it/s]"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Energy: -138.6528032133996 ... not converged.\n",
"2, R, max_bond=(10/20), cutoff:1e-10\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"\n",
"100%|##########################################| 99/99 [00:00<00:00, 347.86it/s]"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Energy: -138.93658456328583 ... not converged.\n",
"3, R, max_bond=(20/100), cutoff:1e-10\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"\n",
"100%|##########################################| 99/99 [00:00<00:00, 165.66it/s]"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Energy: -138.94004900802756 ... not converged.\n",
"4, R, max_bond=(58/100), cutoff:1e-10\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"\n",
"100%|###########################################| 99/99 [00:01<00:00, 67.19it/s]"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Energy: -138.94008561923397 ... not converged.\n",
"5, R, max_bond=(91/200), cutoff:1e-10\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"\n",
"100%|###########################################| 99/99 [00:03<00:00, 29.17it/s]"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Energy: -138.94008606447912 ... converged!\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"\n"
]
},
{
"data": {
"text/plain": [
"np.True_"
]
},
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"dmrg.solve(tol=1e-6, verbosity=1)"
]
},
{
"cell_type": "code",
"execution_count": 20,
"id": "9ba953d0-cf43-4213-9071-561058a57fb9",
"metadata": {
"tags": []
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" 3 9 27 54 64 73 78 83 86 90 91 92 93 95 95 94 94 94 94 94 93 93 92 92 \n",
"... >─>─>──>──>──>──>──>──>──>──>──>──>──>──>──>──>──>──>──>──>──>──>──>── ...\n",
" │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ \n",
" ... \n",
" 91 91 91 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 \n",
"... >──>──>──>──>──>──>──>──>──>──>──>──>──>──>──>──>──>──>──>──>──>──>──> ...\n",
" │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ \n",
" ... \n",
" 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 9 \n",
"... ──>──>──>──>──>──>──>──>──>──>──>──>──>──>──>──>──>──>──>──>──>──>──>─ ...\n",
" │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ \n",
" ... \n",
" 0 90 90 90 90 90 90 90 91 93 96 96 95 96 95 96 96 94 92 90 87 83 78 73 \n",
"... ─>──>──>──>──>──>──>──>──>──>──>──>──>──>──>──>──>──>──>──>──>──>──>── ...\n",
" │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ \n",
" ... \n",
" 64 53 27 9 3 \n",
" >──>──>──>─>─●\n",
" │ │ │ │ │ │\n"
]
}
],
"source": [
"dmrg.state.show(max_width=80)"
]
},
{
"cell_type": "markdown",
"id": "e8164206-872c-4b0d-b35d-805bb991c839",
"metadata": {
"raw_mimetype": "text/restructuredtext"
},
"source": [
"There are many options stored in the dict `DMRG.opts` - an explanation of each of\n",
"these is given in {func}`~quimb.tensor.tn1d.dmrg.get_default_opts`, and it may be\n",
"necessary to tweak these to achieve the best performance/accuracy, especially for\n",
"PBC (see {ref}`examples`).\n",
"\n",
":::{note}\n",
"Performance Tips\n",
"\n",
"1. Make sure numpy is linked to a fast BLAS (e.g. MKL version that comes with conda).\n",
"2. Install slepc4py, to use as the iterative eigensolver, it's faster than scipy.\n",
"3. If the hamiltonian is real, compile and use a real version of SLEPC\n",
" (set the environment variable PETSC_ARCH before launch).\n",
"4. Periodic systems are in some ways easier to solve if *longer*, since this\n",
" reduces correlations the 'long way round'.\n",
":::\n",
"\n",
"\n",
"## Quick TEBD Intro\n",
"\n",
"Time Evolving Block Decimation ({class}`~quimb.tensor.tensor_tebd.TEBD`) requires not a\n",
"MPO but a specficiation of the local, interacting term(s) of a Hamiltonian.\n",
"This is encapsulated in the {class}`~quimb.tensor.tensor_tebd.LocalHam1D` object, which is\n",
"initialized with the sum of two site terms `H2` and one-site terms (if any), `H1`.\n",
"\n",
"{class}`~quimb.tensor.tensor_tebd.LocalHam1D` objects can also be built directly\n",
"from a {class}`~quimb.tensor.tensor_builder.SpinHam1D` instance\n",
"using the {meth}`~quimb.tensor.tensor_builder.SpinHam1D.build_local_ham` method.\n",
"There are also the following built-in LocalHam1D Hamiltonians:\n",
"\n",
"- {class}`~quimb.tensor.tensor_builder.ham1d_heis`\n",
"- {class}`~quimb.tensor.tensor_builder.ham1d_ising`\n",
"- {class}`~quimb.tensor.tensor_builder.ham1d_XY`\n",
"\n",
"Here we build a {class}`~quimb.tensor.tensor_tebd.LocalHam1D` using a\n",
"`SpinHam1D`:"
]
},
{
"cell_type": "code",
"execution_count": 21,
"id": "bac273c7-a5fa-4d2c-861c-833f38ccf722",
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"text/plain": [
"array([[ 0.175, 0. , 0. , 0. ],\n",
" [ 0. , -0.275, 0.5 , 0. ],\n",
" [ 0. , 0.5 , -0.225, 0. ],\n",
" [ 0. , 0. , 0. , 0.325]])"
]
},
"execution_count": 21,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"builder = qtn.SpinHam1D(S=1 / 2)\n",
"builder.add_term(1.0, \"Z\", \"Z\")\n",
"builder.add_term(0.9, \"Y\", \"Y\")\n",
"builder.add_term(0.8, \"X\", \"X\")\n",
"builder.add_term(0.6, \"Z\")\n",
"\n",
"H = qtn.ham_1d_heis(20, bz=0.1)\n",
"\n",
"# check the two site term\n",
"H.terms[0, 1]"
]
},
{
"cell_type": "markdown",
"id": "6698cb4d-980e-4ba5-be79-ea0b0795e045",
"metadata": {
"raw_mimetype": "text/restructuredtext"
},
"source": [
"Then we set up an initial state and the {class}`~quimb.tensor.tensor_tebd.TEBD` object itself -\n",
"which mimics the general api of {class}`quimb.Evolution`:"
]
},
{
"cell_type": "code",
"execution_count": 22,
"id": "1ad5422a-785c-4a68-beab-268a55a71ad8",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"psi0 = qtn.MPS_neel_state(20)\n",
"tebd = qtn.TEBD(psi0, H)"
]
},
{
"cell_type": "markdown",
"id": "de74d837-f9b9-4195-9b2c-8fe9c1b0cfca",
"metadata": {},
"source": [
"Now we are ready to evolve. By setting a ``tol``, the required timestep ``dt`` is computed for us:"
]
},
{
"cell_type": "code",
"execution_count": 23,
"id": "0bb74593-6568-463f-8ecf-8660e6b1b788",
"metadata": {
"tags": []
},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"t=3, max-bond=34: 100%|##########| 100/100 [00:01<00:00, 70.82%/s] \n"
]
}
],
"source": [
"tebd.update_to(T=3, tol=1e-3)"
]
},
{
"cell_type": "markdown",
"id": "53150b8e-4edd-4ea5-a5d4-a15e16c9ed42",
"metadata": {},
"source": [
"After the evolution we can see that entanglement has been generated throughout the chain:"
]
},
{
"cell_type": "code",
"execution_count": 24,
"id": "de23771b-7f54-40c7-b5e7-0674a9e168cb",
"metadata": {
"tags": []
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" 2 4 8 16 29 34 33 34 33 34 33 34 33 34 29 16 8 4 2 \n",
">─>─>─>──>──>──>──>──>──>──>──>──>──>──>──>──>─>─>─●\n",
"│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │\n"
]
}
],
"source": [
"tebd.pt.show()"
]
},
{
"cell_type": "markdown",
"id": "a3c17c88-81d0-49c1-aef7-d0e2914606b3",
"metadata": {},
"source": [
"We can estimate the fidelity (and so error) by tracking the norm of the MPS,\n",
"making use of the canonical form:"
]
},
{
"cell_type": "code",
"execution_count": 25,
"id": "77d705e0-f2f0-4235-9f38-69b15bdc6513",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"np.float64(4.891306415455432e-08)"
]
},
"execution_count": 25,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"nrm = tebd._pt[-1].norm()\n",
"err = 1 - nrm**2\n",
"err"
]
},
{
"cell_type": "markdown",
"id": "0688c7d1-1de5-414f-bb91-92f107faf689",
"metadata": {
"raw_mimetype": "text/restructuredtext"
},
"source": [
"Which approximates $1 - |\\langle \\psi(t) | \\psi_\\mathrm{truncated}(t) \\rangle|^2$. Note this only approximates error coming from the truncations, not the trotterization.\n",
"\n",
"A more complete demonstration can be found in the {ref}`examples`."
]
},
{
"cell_type": "markdown",
"id": "e2917b46-d815-44dd-aaf5-bb39702dac53",
"metadata": {
"raw_mimetype": "text/restructuredtext"
},
"source": [
"(gating)=\n",
"\n",
"## Gates: compute local quantities and simulate circuits\n",
"\n",
"On top of the builtin methods mentioned earlier\n",
"({meth}`~quimb.tensor.tn1d.core.MatrixProductState.entropy`,\n",
"{meth}`~quimb.tensor.tn1d.core.MatrixProductState.schmidt_gap`,\n",
"{meth}`~quimb.tensor.tn1d.core.MatrixProductState.magnetization`,\n",
"{meth}`~quimb.tensor.tn1d.core.TensorNetwork1DVector.correlation`,\n",
"{meth}`~quimb.tensor.tn1d.core.MatrixProductState.logneg_subsys`, etc.),\n",
"many other quantities are encapsulated by the\n",
"{meth}`~quimb.tensor.tn1d.core.TensorNetwork1DVector.gate` method,\n",
"which works on any 1D tensor network vector (MPS, MERA, etc.).\n",
"This 'applies' a given operator to 1 or more sites, whilst maintaining\n",
"the 'physical', outer indices.\n",
"This not only directly allows quantum circuit style computation simulation\n",
"but also makes local quantities (i.e. non-MPO) easy to compute:"
]
},
{
"cell_type": "code",
"execution_count": 26,
"id": "ed4b95ca-d75d-486a-8ab3-afb3306b7411",
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"text/plain": [
"[np.complex128(1+0j),\n",
" np.complex128(-1+0j),\n",
" np.complex128(1+0j),\n",
" np.complex128(-1+0j),\n",
" np.complex128(1+0j),\n",
" np.complex128(-1+0j),\n",
" np.complex128(1+0j),\n",
" np.complex128(-1+0j),\n",
" np.complex128(1+0j),\n",
" np.complex128(-1+0j)]"
]
},
"execution_count": 26,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import quimb as qu\n",
"\n",
"Z = qu.pauli(\"Z\")\n",
"\n",
"# compute for neel state above\n",
"[psi0.gate(Z, i).H @ psi0 for i in range(10)]"
]
},
{
"cell_type": "markdown",
"id": "48443f9e-7a2a-4f01-8aa0-871b0189eab1",
"metadata": {
"raw_mimetype": "text/restructuredtext"
},
"source": [
"There are four ways in which a gate can be applied:\n",
"\n",
"- Lazily (`contract=False`) - the gate is added to the tensor network\n",
" but nothing is contracted. This is the default.\n",
"- Lazily with split (`contract='split-gate'`) - the gate is split before\n",
" it is added to the network.\n",
"- Eagerly (`contract=True`) - the gate is contracted into the tensor\n",
" network. If the gate acts on more than one site this will produce\n",
" larger tensors.\n",
"- Swap and Split (`contract='swap+split'`) - sites will be swapped\n",
" until adjacent, the gate will be applied and the resulting\n",
" tensor split, then the sites swapped back into their original positions.\n",
" This explicitly maintains the exact structure of an MPS (at the cost of\n",
" increasing bond dimension), unlike the other two methods.\n",
"\n",
"Here's a quantum computation style demonstration of the lazy method:"
]
},
{
"cell_type": "code",
"execution_count": 27,
"id": "d33e9dbc-a47b-4d98-b823-c3f7143cdb8a",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"import quimb as qu\n",
"\n",
"# some operators to apply\n",
"H = qu.hadamard()\n",
"CNOT = qu.controlled(\"not\")\n",
"\n",
"# setup an intitial register of qubits\n",
"n = 10\n",
"psi0 = qtn.MPS_computational_state(\"0\" * n, tags=\"PSI0\")\n",
"\n",
"# apply hadamard to each site\n",
"for i in range(n):\n",
" psi0.gate_(H, i, tags=\"H\")\n",
"\n",
"# apply CNOT to even pairs\n",
"for i in range(0, n, 2):\n",
" psi0.gate_(CNOT, (i, i + 1), tags=\"CNOT\")\n",
"\n",
"# apply CNOT to odd pairs\n",
"for i in range(1, n - 1, 2):\n",
" psi0.gate_(CNOT, (i, i + 1), tags=\"CNOT\")"
]
},
{
"cell_type": "markdown",
"id": "b084dc1e-008d-437f-a59e-7bddf5bfddba",
"metadata": {},
"source": [
"Note we have used the inplace ``gate_`` (with a trailing\n",
"underscore) which modifies the original ``psi0`` object.\n",
"However ``psi0`` has its physical site indices mantained\n",
"such that it overall looks like the same object:"
]
},
{
"cell_type": "code",
"execution_count": 28,
"id": "97ef9be3-853f-49b5-a5dd-6437b80199df",
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"text/plain": [
"['k0', 'k1', 'k2', 'k3', 'k4', 'k5', 'k6', 'k7', 'k8', 'k9']"
]
},
"execution_count": 28,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"sorted(psi0.outer_inds())"
]
},
{
"cell_type": "code",
"execution_count": 29,
"id": "323e9f2c-9ba2-4fc9-b6ae-3593c8b6cffa",
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"text/plain": [
"np.complex128(0.9999999999999981+0j)"
]
},
"execution_count": 29,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"(psi0.H & psi0) ^ all"
]
},
{
"cell_type": "markdown",
"id": "7a97ed53-76e2-4dbe-b767-49250c1f3a1f",
"metadata": {},
"source": [
"But the network now contains the gates as additional tensors:"
]
},
{
"cell_type": "code",
"execution_count": 30,
"id": "ea3d0822-c281-4a59-95ec-a5358d06b6b4",
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"image/svg+xml": [
""
],
"text/plain": [
""
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"psi0.draw(color=[\"PSI0\", \"H\", \"CNOT\"], show_tags=False, layout=\"neato\")"
]
},
{
"cell_type": "markdown",
"id": "85c93d01-5fe2-4144-a44a-7d36883b5221",
"metadata": {},
"source": [
"With the swap and split method MPS form is always maintained, which\n",
"allows a canonical form and thus optimal trimming of singular values:"
]
},
{
"cell_type": "code",
"execution_count": 31,
"id": "a2eaee46-cd1a-401e-b783-8690b9a11100",
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"text/html": [
"MatrixProductState(tensors=10, indices=19, L=10, max_bond=4)
Tensor(shape=(2, 2), inds=[_5f4cf2AADAL, k0], tags={I0}),
backend=numpy, dtype=complex128, data=array([[-0.69157229-0.14740341j, -0.57136173-0.41658825j],\n",
" [ 0.14740341-0.69157229j, -0.41658825+0.57136173j]])Tensor(shape=(2, 2, 2), inds=[_5f4cf2AADAL, _5f4cf2AADAM, k1], tags={I1}),
backend=numpy, dtype=complex128, data=array([[[-0.63146701-0.28199583j, -0.63146701-0.28199583j],\n",
" [ 0.28199583-0.63146701j, -0.28199583+0.63146701j]],\n",
"\n",
" [[ 0.13459242+0.06010528j, -0.13459242-0.06010528j],\n",
" [-0.06010528+0.13459242j, -0.06010528+0.13459242j]]])Tensor(shape=(2, 4, 2), inds=[_5f4cf2AADAM, _5f4cf2AADAN, k2], tags={I2}),
backend=numpy, dtype=complex128, data=array([[[-0.69157229+0.00000000e+00j, -0.69157229-1.92200763e-16j],\n",
" [ 0.69157229-3.24057678e-32j, -0.69157229-3.44222998e-16j],\n",
" [-0.14740341-1.29623071e-31j, -0.14740341-6.38089810e-16j],\n",
" [-0.14740341-7.56134582e-32j, 0.14740341-7.51526232e-17j]],\n",
"\n",
" [[ 0.14740341+3.02452747e-17j, -0.14740341-7.43374196e-17j],\n",
" [-0.14740341-3.97552691e-16j, -0.14740341+2.71597597e-16j],\n",
" [-0.69157229-1.89107190e-15j, 0.69157229+1.40112251e-15j],\n",
" [-0.69157229-1.16027005e-16j, -0.69157229+2.21900145e-16j]]])Tensor(shape=(4, 4, 2), inds=[_5f4cf2AADAN, _5f4cf2AADAO, k3], tags={I3}),
backend=numpy, dtype=complex128, data=array([[[-6.31467011e-01-2.81995831e-01j,\n",
" -6.31467011e-01-2.81995831e-01j],\n",
" [-4.43422420e-02+1.34187125e-02j,\n",
" 4.43422420e-02-1.34187125e-02j],\n",
" [-6.16249504e-01-3.10423079e-01j,\n",
" 6.16249504e-01+3.10423079e-01j],\n",
" [-2.30224128e-17+2.37605136e-17j,\n",
" -8.39388094e-17+1.39084791e-16j]],\n",
"\n",
" [[ 1.18292190e-16-1.18292292e-16j,\n",
" -2.30706319e-16+5.88643844e-17j],\n",
" [-5.67616265e-01-3.92348970e-01j,\n",
" -5.67616265e-01-3.92348970e-01j],\n",
" [ 9.45370719e-03+4.53533206e-02j,\n",
" 9.45370719e-03+4.53533206e-02j],\n",
" [ 2.25392330e-01+6.53812307e-01j,\n",
" -2.25392330e-01-6.53812307e-01j]],\n",
"\n",
" [[ 1.34592422e-01+6.01052807e-02j,\n",
" -1.34592422e-01-6.01052807e-02j],\n",
" [ 9.45121385e-03-2.86009717e-03j,\n",
" 9.45121385e-03-2.86009717e-03j],\n",
" [ 1.31348926e-01+6.61643337e-02j,\n",
" 1.31348926e-01+6.61643337e-02j],\n",
" [ 2.39847456e-16-2.73585521e-16j,\n",
" -2.33327540e-16+5.19373496e-16j]],\n",
"\n",
" [[-1.87848567e-17-1.33775720e-17j,\n",
" 1.80532536e-17+1.01860403e-17j],\n",
" [-1.20983118e-01-8.36262186e-02j,\n",
" 1.20983118e-01+8.36262186e-02j],\n",
" [ 2.01498626e-03+9.66671762e-03j,\n",
" -2.01498626e-03-9.66671762e-03j],\n",
" [ 4.80406723e-02+1.39355153e-01j,\n",
" 4.80406723e-02+1.39355153e-01j]]])Tensor(shape=(4, 4, 2), inds=[_5f4cf2AADAO, _5f4cf2AADAP, k4], tags={I4}),
backend=numpy, dtype=complex128, data=array([[[-6.91572292e-01+2.33774154e-17j,\n",
" -6.91572292e-01-2.14415947e-16j],\n",
" [ 1.21580135e-16+3.07063397e-17j,\n",
" -1.86205197e-16-5.03093435e-17j],\n",
" [ 1.44673123e-01-2.82391996e-02j,\n",
" 1.44673123e-01-2.82391996e-02j],\n",
" [-2.50524625e-16-8.86124285e-17j,\n",
" 2.54477847e-16+7.69517183e-17j]],\n",
"\n",
" [[-6.46535434e-03+7.46356432e-03j,\n",
" 6.46535434e-03-7.46356432e-03j],\n",
" [ 6.89760290e-01+1.88860077e-02j,\n",
" 6.89760290e-01+1.88860077e-02j],\n",
" [-2.30632026e-02+4.01794096e-02j,\n",
" 2.30632026e-02-4.01794096e-02j],\n",
" [ 1.45873807e-01+1.87374461e-02j,\n",
" 1.45873807e-01+1.87374461e-02j]],\n",
"\n",
" [[ 6.85502397e-03+1.46912450e-01j,\n",
" -6.85502397e-03-1.46912450e-01j],\n",
" [-3.44263234e-02+3.10020085e-02j,\n",
" -3.44263234e-02+3.10020085e-02j],\n",
" [ 1.63614500e-01+6.70340387e-01j,\n",
" -1.63614500e-01-6.70340387e-01j],\n",
" [-7.96293521e-03+5.83928609e-03j,\n",
" -7.96293521e-03+5.83928609e-03j]],\n",
"\n",
" [[-9.86764738e-18-1.60450901e-17j,\n",
" 1.32312102e-17+1.46154604e-17j],\n",
" [ 8.40355753e-02+1.21102382e-01j,\n",
" -8.40355753e-02-1.21102382e-01j],\n",
" [-2.43479473e-17-7.39381597e-17j,\n",
" 4.18529171e-17+9.52415259e-17j],\n",
" [-3.35349238e-01-6.04824870e-01j,\n",
" 3.35349238e-01+6.04824870e-01j]]])Tensor(shape=(4, 4, 2), inds=[_5f4cf2AADAP, _5f4cf2AADAQ, k5], tags={I5}),
backend=numpy, dtype=complex128, data=array([[[-6.37043484e-01-2.69161353e-01j,\n",
" -6.37043484e-01-2.69161353e-01j],\n",
" [ 6.83902712e-01+1.02709861e-01j,\n",
" -6.83902712e-01-1.02709861e-01j],\n",
" [-1.26634814e-15+3.71237653e-16j,\n",
" 1.31039650e-15-3.37047042e-16j],\n",
" [ 1.99483809e-17+8.95352913e-17j,\n",
" 9.12636202e-18-9.19128784e-17j]],\n",
"\n",
" [[ 1.08108324e-17+7.78973755e-18j,\n",
" 2.39890221e-17+2.46729250e-17j],\n",
" [-7.29244663e-16+1.05679617e-15j,\n",
" -7.36384475e-16+1.09355767e-15j],\n",
" [-1.28966374e-01+6.79440880e-01j,\n",
" -1.28966374e-01+6.79440880e-01j],\n",
" [-6.78885723e-01-1.31857537e-01j,\n",
" 6.78885723e-01+1.31857537e-01j]],\n",
"\n",
" [[-1.22275242e-01-8.23196827e-02j,\n",
" 1.22275242e-01+8.23196827e-02j],\n",
" [ 1.38874703e-01+4.94123636e-02j,\n",
" 1.38874703e-01+4.94123636e-02j],\n",
" [-3.40615138e-16+2.43576392e-17j,\n",
" -1.81191878e-16-4.71773520e-17j],\n",
" [ 1.57670259e-17-1.40816102e-16j,\n",
" 5.43958851e-17-1.13098033e-16j]],\n",
"\n",
" [[-1.83380157e-17-3.59165792e-18j,\n",
" 1.32480315e-17+7.94836478e-18j],\n",
" [ 1.02324291e-16-2.67717461e-16j,\n",
" -4.59595226e-17+2.29418624e-16j],\n",
" [ 1.28379565e-02-1.46843290e-01j,\n",
" -1.28379565e-02+1.46843290e-01j],\n",
" [ 1.46787309e-01+1.34629416e-02j,\n",
" 1.46787309e-01+1.34629416e-02j]]])Tensor(shape=(4, 4, 2), inds=[_5f4cf2AADAQ, _5f4cf2AADAR, k6], tags={I6}),
backend=numpy, dtype=complex128, data=array([[[-6.25631994e-01-2.94714850e-01j,\n",
" -6.25631994e-01-2.94714850e-01j],\n",
" [-4.05481713e-18+2.44966954e-17j,\n",
" 1.29809761e-17-1.42022029e-17j],\n",
" [-2.15332057e-02+1.45822104e-01j,\n",
" -2.15332057e-02+1.45822104e-01j],\n",
" [ 8.04911693e-16-1.67659106e-17j,\n",
" -2.35073872e-16+3.06637867e-16j]],\n",
"\n",
" [[ 9.39336731e-02-1.13596787e-01j,\n",
" -9.39336731e-02+1.13596787e-01j],\n",
" [ 3.29582028e-16-1.18564047e-15j,\n",
" 2.94168347e-16-1.14773437e-15j],\n",
" [ 6.37703635e-01+2.67593552e-01j,\n",
" -6.37703635e-01-2.67593552e-01j],\n",
" [ 3.07367486e-16+1.46546772e-16j,\n",
" 3.34815572e-16-4.20113798e-18j]],\n",
"\n",
" [[-1.67578126e-16+1.34053224e-16j,\n",
" 2.91981056e-16-7.79568283e-17j],\n",
" [ 4.46871322e-01-5.27805132e-01j,\n",
" 4.46871322e-01-5.27805132e-01j],\n",
" [-7.95810243e-16-9.12430551e-16j,\n",
" 7.69749507e-16+9.22781282e-16j],\n",
" [ 1.33348733e-01+6.28162436e-02j,\n",
" 1.33348733e-01+6.28162436e-02j]],\n",
"\n",
" [[ 2.99618669e-16+1.40938991e-16j,\n",
" -2.97552502e-16-1.34366828e-16j],\n",
" [-9.47674882e-02+1.12902117e-01j,\n",
" 9.47674882e-02-1.12902117e-01j],\n",
" [ 4.11696377e-17-6.47277436e-17j,\n",
" 7.62672842e-17+2.72874078e-17j],\n",
" [ 6.26880905e-01+2.92048909e-01j,\n",
" -6.26880905e-01-2.92048909e-01j]]])Tensor(shape=(4, 2, 2), inds=[_5f4cf2AADAR, _5f4cf2AADAS, k7], tags={I7}),
backend=numpy, dtype=complex128, data=array([[[-6.91572292e-01-1.05149020e-16j,\n",
" -6.91572292e-01+1.66996973e-16j],\n",
" [ 1.15557254e-15-1.08480257e-15j,\n",
" 3.96170892e-16+1.10392349e-15j]],\n",
"\n",
" [[ 3.39077831e-16+1.61110002e-15j,\n",
" -5.38364629e-16-1.53543397e-15j],\n",
" [ 1.79337702e-01+6.67914833e-01j,\n",
" -1.79337702e-01-6.67914833e-01j]],\n",
"\n",
" [[-4.26623181e-02+1.41094619e-01j,\n",
" 4.26623181e-02-1.41094619e-01j],\n",
" [ 8.48212361e-16-3.41949244e-15j,\n",
" -1.26027277e-15+3.49278967e-15j]],\n",
"\n",
" [[-3.12672327e-17-1.80482807e-17j,\n",
" -4.14174925e-17+1.81688921e-17j],\n",
" [-1.47403409e-01+3.05827721e-16j,\n",
" -1.47403409e-01-4.14227662e-17j]]])Tensor(shape=(2, 2, 2), inds=[_5f4cf2AADAS, _5f4cf2AADAT, k8], tags={I8}),
backend=numpy, dtype=complex128, data=array([[[-0.67637908+0.00000000e+00j, -0.67637908-1.36438116e-16j],\n",
" [-0.0307277 -3.73587769e-17j, -0.0307277 -3.46082528e-17j]],\n",
"\n",
" [[-0.14416509+0.00000000e+00j, 0.14416509+2.90787437e-17j],\n",
" [ 0.14416509-6.51903894e-18j, -0.14416509+1.94679072e-17j]]])Tensor(shape=(2, 2), inds=[_5f4cf2AADAT, k9], tags={I9}),
backend=numpy, dtype=complex128, data=array([[-0.70710678+0.00000000e+00j, -0.70710678+3.03974502e-17j],\n",
" [ 0.70710678-1.54308049e-33j, -0.70710678+3.03974502e-17j]]) "
],
"text/plain": [
"MatrixProductState(tensors=10, indices=19, L=10, max_bond=4)"
]
},
"execution_count": 31,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"n = 10\n",
"psi0 = qtn.MPS_computational_state(\"0\" * n)\n",
"\n",
"for i in range(n):\n",
" # 'swap+split' will be ignore to one-site gates\n",
" psi0.gate_(H, i, contract=\"swap+split\")\n",
"\n",
"# use Z-phase to create entanglement\n",
"Rz = qu.phase_gate(0.42)\n",
"for i in range(n):\n",
" psi0.gate_(Rz, i, contract=\"swap+split\")\n",
"\n",
"for i in range(0, n, 2):\n",
" psi0.gate_(CNOT, (i, i + 1), contract=\"swap+split\")\n",
"\n",
"for i in range(1, n - 1, 2):\n",
" psi0.gate_(CNOT, (i, i + 1), contract=\"swap+split\")\n",
"\n",
"# act with one long-range CNOT\n",
"psi0.gate_(CNOT, (2, n - 2), contract=\"swap+split\")"
]
},
{
"cell_type": "markdown",
"id": "c47ed534-b987-456d-922a-dc8e50fa1ef0",
"metadata": {},
"source": [
"We now still have an MPS, but with increased bond dimension:"
]
},
{
"cell_type": "code",
"execution_count": 32,
"id": "5822d28a-a12f-4c7a-9452-75d4b0777cbc",
"metadata": {
"tags": []
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" 2 2 4 4 4 4 4 2 2 \n",
">─>─>─>─>─>─>─>─●─<\n",
"│ │ │ │ │ │ │ │ │ │\n"
]
}
],
"source": [
"psi0.show()"
]
},
{
"cell_type": "markdown",
"id": "b3e94387-9804-4c70-894f-4111a596dd2f",
"metadata": {},
"source": [
"Finally, the eager (``contract=True``) method works fairly simply:"
]
},
{
"cell_type": "code",
"execution_count": 33,
"id": "6fe1d16f-ed63-46c4-9e2a-be80e7cb722b",
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"image/svg+xml": [
""
],
"text/plain": [
""
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"psi0_CNOT = psi0.gate(CNOT, (1, n - 2), contract=True)\n",
"psi0_CNOT.draw(color=[psi0.site_tag(i) for i in range(n)])"
]
},
{
"cell_type": "markdown",
"id": "5651a865-a453-4b5b-908d-cceeea9ac629",
"metadata": {
"raw_mimetype": "text/restructuredtext"
},
"source": [
"Where we can see that the gate, site 1, and site 8 have been combined\n",
"into a new rank-6 tensor.\n",
"\n",
"A much more detailed run-through of quantum circuit simulation using\n",
"tensor networks and the {class}`~quimb.tensor.circuit.Circuit` object\n",
"can be found in the example {ref}`quantum-circuit-example`."
]
}
],
"metadata": {
"celltoolbar": "Raw Cell Format",
"kernel_info": {
"name": "python3"
},
"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"
}
},
"nbformat": 4,
"nbformat_minor": 4
}