From f5ee89c981b615ec059d42fb34ce192fa80b48dc Mon Sep 17 00:00:00 2001 From: leburgel Date: Wed, 19 Jun 2024 14:05:42 +0200 Subject: [PATCH 1/4] Rewrite local expectation values as a single contraction, switch `opt=true` --- src/operators/localoperator.jl | 68 +++++++++++++++++++++++++++++----- 1 file changed, 59 insertions(+), 9 deletions(-) diff --git a/src/operators/localoperator.jl b/src/operators/localoperator.jl index 5f8e57b5..14bf424d 100644 --- a/src/operators/localoperator.jl +++ b/src/operators/localoperator.jl @@ -35,7 +35,7 @@ operator_env function operator_env(peps::InfinitePEPS, env::CTMRGEnv, ::OnSite) return map(Iterators.product(axes(env.corners, 2), axes(env.corners, 3))) do (r, c) - @tensor ρ[-1; -2] := + @tensor opt = true ρ[-1; -2] := env.corners[NORTHWEST, r, c][1; 2] * env.edges[NORTH, r, c][2 3 4; 5] * env.corners[NORTHEAST, r, c][5; 6] * @@ -52,7 +52,7 @@ end function operator_env(peps::InfinitePEPS, env::CTMRGEnv, ::NearestNeighbor) return map(Iterators.product(axes(env.corners, 2), axes(env.corners, 3))) do (r, c) cnext = _next(c, size(peps, 2)) - @tensor ρ[-11 -20; -12 -18] := + @tensor opt = true ρ[-12 -18; -11 -20] := env.corners[NORTHWEST, r, c][1; 3] * env.edges[NORTH, r, c][3 5 8; 13] * env.edges[NORTH, r, cnext][13 16 22; 23] * @@ -78,10 +78,31 @@ of `peps` and `env`. """ MPSKit.expectation_value(::InfinitePEPS, ::Any, ::NLocalOperator) # 1-site operator expectation values on unit cell -function MPSKit.expectation_value(peps::InfinitePEPS, env, O::NLocalOperator{OnSite}) - return map(operator_env(peps, env, OnSite())) do ρ - o = @tensor ρ[-1; -2] * O.op[-1; -2] - n = @tensor ρ[-1; -1] +function MPSKit.expectation_value(peps::InfinitePEPS, env::CTMRGEnv, O::NLocalOperator{OnSite}) + return map(Iterators.product(axes(env.corners, 2), axes(env.corners, 3))) do (r, c) + o = @tensor opt = true env.corners[NORTHWEST, r, c][1; 2] * + env.edges[NORTH, r, c][2 3 4; 5] * + env.corners[NORTHEAST, r, c][5; 6] * + env.edges[EAST, r, c][6 7 8; 9] * + env.corners[SOUTHEAST, r, c][9; 10] * + env.edges[SOUTH, r, c][10 11 12; 13] * + env.corners[SOUTHWEST, r, c][13; 14] * + env.edges[WEST, r, c][14 15 16; 1] * + peps[r, c][17; 3 7 11 15] * + conj(peps[r, c][18; 4 8 12 16]) * + O.op[18; 17] + + n = @tensor opt = true env.corners[NORTHWEST, r, c][1; 2] * + env.edges[NORTH, r, c][2 3 4; 5] * + env.corners[NORTHEAST, r, c][5; 6] * + env.edges[EAST, r, c][6 7 8; 9] * + env.corners[SOUTHEAST, r, c][9; 10] * + env.edges[SOUTH, r, c][10 11 12; 13] * + env.corners[SOUTHWEST, r, c][13; 14] * + env.edges[WEST, r, c][14 15 16; 1] * + peps[r, c][17; 3 7 11 15] * + conj(peps[r, c][17; 4 8 12 16]) + o / n end end @@ -89,9 +110,38 @@ end function MPSKit.expectation_value( peps::InfinitePEPS, env, O::NLocalOperator{NearestNeighbor} ) - return map(operator_env(peps, env, NearestNeighbor())) do ρ - o = @tensor ρ[1 2; 3 4] * O.op[1 2; 3 4] - n = @tensor ρ[1 2; 1 2] + return map(Iterators.product(axes(env.corners, 2), axes(env.corners, 3))) do (r, c) + cnext = _next(c, size(peps, 2)) + o = @tensor opt = true env.corners[NORTHWEST, r, c][1; 3] * + env.edges[NORTH, r, c][3 5 8; 13] * + env.edges[NORTH, r, cnext][13 16 22; 23] * + env.corners[NORTHEAST, r, cnext][23; 24] * + env.edges[EAST, r, cnext][24 25 26; 27] * + env.corners[SOUTHEAST, r, cnext][27; 28] * + env.edges[SOUTH, r, cnext][28 17 21; 14] * + env.edges[SOUTH, r, c][14 6 10; 4] * + env.corners[SOUTHWEST, r, c][4; 2] * + env.edges[WEST, r, c][2 7 9; 1] * + peps[r, c][29; 5 15 6 7] * + conj(peps[r, c][31; 8 19 10 9]) * + peps[r, cnext][30; 16 25 17 15] * + conj(peps[r, cnext][32; 22 26 21 19]) * + O.op[31 32; 29 30] + + n = @tensor opt = true env.corners[NORTHWEST, r, c][1; 3] * + env.edges[NORTH, r, c][3 5 8; 13] * + env.edges[NORTH, r, cnext][13 16 22; 23] * + env.corners[NORTHEAST, r, cnext][23; 24] * + env.edges[EAST, r, cnext][24 25 26; 27] * + env.corners[SOUTHEAST, r, cnext][27; 28] * + env.edges[SOUTH, r, cnext][28 17 21; 14] * + env.edges[SOUTH, r, c][14 6 10; 4] * + env.corners[SOUTHWEST, r, c][4; 2] * + env.edges[WEST, r, c][2 7 9; 1] * + peps[r, c][29; 5 15 6 7] * + conj(peps[r, c][29; 8 19 10 9]) * + peps[r, cnext][30; 16 25 17 15] * + conj(peps[r, cnext][30; 22 26 21 19]) o / n end end From d67dee358071d9ead6c7e9c35f57b49f0ae77efb Mon Sep 17 00:00:00 2001 From: leburgel Date: Wed, 19 Jun 2024 14:16:32 +0200 Subject: [PATCH 2/4] Format --- src/operators/localoperator.jl | 110 +++++++++++++++++---------------- 1 file changed, 56 insertions(+), 54 deletions(-) diff --git a/src/operators/localoperator.jl b/src/operators/localoperator.jl index 14bf424d..778c6bcf 100644 --- a/src/operators/localoperator.jl +++ b/src/operators/localoperator.jl @@ -78,31 +78,33 @@ of `peps` and `env`. """ MPSKit.expectation_value(::InfinitePEPS, ::Any, ::NLocalOperator) # 1-site operator expectation values on unit cell -function MPSKit.expectation_value(peps::InfinitePEPS, env::CTMRGEnv, O::NLocalOperator{OnSite}) +function MPSKit.expectation_value( + peps::InfinitePEPS, env::CTMRGEnv, O::NLocalOperator{OnSite} +) return map(Iterators.product(axes(env.corners, 2), axes(env.corners, 3))) do (r, c) - o = @tensor opt = true env.corners[NORTHWEST, r, c][1; 2] * - env.edges[NORTH, r, c][2 3 4; 5] * - env.corners[NORTHEAST, r, c][5; 6] * - env.edges[EAST, r, c][6 7 8; 9] * - env.corners[SOUTHEAST, r, c][9; 10] * - env.edges[SOUTH, r, c][10 11 12; 13] * - env.corners[SOUTHWEST, r, c][13; 14] * - env.edges[WEST, r, c][14 15 16; 1] * - peps[r, c][17; 3 7 11 15] * - conj(peps[r, c][18; 4 8 12 16]) * - O.op[18; 17] - - n = @tensor opt = true env.corners[NORTHWEST, r, c][1; 2] * - env.edges[NORTH, r, c][2 3 4; 5] * - env.corners[NORTHEAST, r, c][5; 6] * - env.edges[EAST, r, c][6 7 8; 9] * - env.corners[SOUTHEAST, r, c][9; 10] * - env.edges[SOUTH, r, c][10 11 12; 13] * - env.corners[SOUTHWEST, r, c][13; 14] * - env.edges[WEST, r, c][14 15 16; 1] * - peps[r, c][17; 3 7 11 15] * - conj(peps[r, c][17; 4 8 12 16]) - + o = @tensor opt = true env.corners[NORTHWEST, r, c][1; 2] * + env.edges[NORTH, r, c][2 3 4; 5] * + env.corners[NORTHEAST, r, c][5; 6] * + env.edges[EAST, r, c][6 7 8; 9] * + env.corners[SOUTHEAST, r, c][9; 10] * + env.edges[SOUTH, r, c][10 11 12; 13] * + env.corners[SOUTHWEST, r, c][13; 14] * + env.edges[WEST, r, c][14 15 16; 1] * + peps[r, c][17; 3 7 11 15] * + conj(peps[r, c][18; 4 8 12 16]) * + O.op[18; 17] + + n = @tensor opt = true env.corners[NORTHWEST, r, c][1; 2] * + env.edges[NORTH, r, c][2 3 4; 5] * + env.corners[NORTHEAST, r, c][5; 6] * + env.edges[EAST, r, c][6 7 8; 9] * + env.corners[SOUTHEAST, r, c][9; 10] * + env.edges[SOUTH, r, c][10 11 12; 13] * + env.corners[SOUTHWEST, r, c][13; 14] * + env.edges[WEST, r, c][14 15 16; 1] * + peps[r, c][17; 3 7 11 15] * + conj(peps[r, c][17; 4 8 12 16]) + o / n end end @@ -112,36 +114,36 @@ function MPSKit.expectation_value( ) return map(Iterators.product(axes(env.corners, 2), axes(env.corners, 3))) do (r, c) cnext = _next(c, size(peps, 2)) - o = @tensor opt = true env.corners[NORTHWEST, r, c][1; 3] * - env.edges[NORTH, r, c][3 5 8; 13] * - env.edges[NORTH, r, cnext][13 16 22; 23] * - env.corners[NORTHEAST, r, cnext][23; 24] * - env.edges[EAST, r, cnext][24 25 26; 27] * - env.corners[SOUTHEAST, r, cnext][27; 28] * - env.edges[SOUTH, r, cnext][28 17 21; 14] * - env.edges[SOUTH, r, c][14 6 10; 4] * - env.corners[SOUTHWEST, r, c][4; 2] * - env.edges[WEST, r, c][2 7 9; 1] * - peps[r, c][29; 5 15 6 7] * - conj(peps[r, c][31; 8 19 10 9]) * - peps[r, cnext][30; 16 25 17 15] * - conj(peps[r, cnext][32; 22 26 21 19]) * - O.op[31 32; 29 30] - - n = @tensor opt = true env.corners[NORTHWEST, r, c][1; 3] * - env.edges[NORTH, r, c][3 5 8; 13] * - env.edges[NORTH, r, cnext][13 16 22; 23] * - env.corners[NORTHEAST, r, cnext][23; 24] * - env.edges[EAST, r, cnext][24 25 26; 27] * - env.corners[SOUTHEAST, r, cnext][27; 28] * - env.edges[SOUTH, r, cnext][28 17 21; 14] * - env.edges[SOUTH, r, c][14 6 10; 4] * - env.corners[SOUTHWEST, r, c][4; 2] * - env.edges[WEST, r, c][2 7 9; 1] * - peps[r, c][29; 5 15 6 7] * - conj(peps[r, c][29; 8 19 10 9]) * - peps[r, cnext][30; 16 25 17 15] * - conj(peps[r, cnext][30; 22 26 21 19]) + o = @tensor opt = true env.corners[NORTHWEST, r, c][1; 3] * + env.edges[NORTH, r, c][3 5 8; 13] * + env.edges[NORTH, r, cnext][13 16 22; 23] * + env.corners[NORTHEAST, r, cnext][23; 24] * + env.edges[EAST, r, cnext][24 25 26; 27] * + env.corners[SOUTHEAST, r, cnext][27; 28] * + env.edges[SOUTH, r, cnext][28 17 21; 14] * + env.edges[SOUTH, r, c][14 6 10; 4] * + env.corners[SOUTHWEST, r, c][4; 2] * + env.edges[WEST, r, c][2 7 9; 1] * + peps[r, c][29; 5 15 6 7] * + conj(peps[r, c][31; 8 19 10 9]) * + peps[r, cnext][30; 16 25 17 15] * + conj(peps[r, cnext][32; 22 26 21 19]) * + O.op[31 32; 29 30] + + n = @tensor opt = true env.corners[NORTHWEST, r, c][1; 3] * + env.edges[NORTH, r, c][3 5 8; 13] * + env.edges[NORTH, r, cnext][13 16 22; 23] * + env.corners[NORTHEAST, r, cnext][23; 24] * + env.edges[EAST, r, cnext][24 25 26; 27] * + env.corners[SOUTHEAST, r, cnext][27; 28] * + env.edges[SOUTH, r, cnext][28 17 21; 14] * + env.edges[SOUTH, r, c][14 6 10; 4] * + env.corners[SOUTHWEST, r, c][4; 2] * + env.edges[WEST, r, c][2 7 9; 1] * + peps[r, c][29; 5 15 6 7] * + conj(peps[r, c][29; 8 19 10 9]) * + peps[r, cnext][30; 16 25 17 15] * + conj(peps[r, cnext][30; 22 26 21 19]) o / n end end From 93f6f553e4a308e0a620d847dac323d29fc527be Mon Sep 17 00:00:00 2001 From: lkdvos Date: Wed, 19 Jun 2024 18:20:55 +0200 Subject: [PATCH 3/4] Optimize contraction orders --- src/operators/localoperator.jl | 81 +++++++++++++++++++++++++++++++--- 1 file changed, 74 insertions(+), 7 deletions(-) diff --git a/src/operators/localoperator.jl b/src/operators/localoperator.jl index 778c6bcf..ffc77c0d 100644 --- a/src/operators/localoperator.jl +++ b/src/operators/localoperator.jl @@ -77,12 +77,18 @@ Evaluate the expectation value of any `NLocalOperator` on each unit-cell entry of `peps` and `env`. """ MPSKit.expectation_value(::InfinitePEPS, ::Any, ::NLocalOperator) +# Optimal contraction order is obtained by manually trying out some space sizes and using costcheck = warn +# in principle, we would like to use opt = true, but this does not give optimal results without also supplying costs +# However, due to a bug in tensoroperations this is currently not possible with integer labels. +# Thus, this is a workaround until the bug is fixed. (otherwise we'd need to rewrite all the labels to symbols...) + # 1-site operator expectation values on unit cell function MPSKit.expectation_value( peps::InfinitePEPS, env::CTMRGEnv, O::NLocalOperator{OnSite} ) return map(Iterators.product(axes(env.corners, 2), axes(env.corners, 3))) do (r, c) - o = @tensor opt = true env.corners[NORTHWEST, r, c][1; 2] * + o = @tensor order = (6, 2, 5, 10, 14, 13, 11, 15, 7, 9, 1, 3, 4, 8, 12, 16, 18, 17) begin + env.corners[NORTHWEST, r, c][1; 2] * env.edges[NORTH, r, c][2 3 4; 5] * env.corners[NORTHEAST, r, c][5; 6] * env.edges[EAST, r, c][6 7 8; 9] * @@ -93,8 +99,9 @@ function MPSKit.expectation_value( peps[r, c][17; 3 7 11 15] * conj(peps[r, c][18; 4 8 12 16]) * O.op[18; 17] - - n = @tensor opt = true env.corners[NORTHWEST, r, c][1; 2] * + end + n = @tensor order = (9, 13, 10, 5, 1, 2, 4, 16, 6, 8, 14, 12, 17, 3, 7, 11, 15) begin + env.corners[NORTHWEST, r, c][1; 2] * env.edges[NORTH, r, c][2 3 4; 5] * env.corners[NORTHEAST, r, c][5; 6] * env.edges[EAST, r, c][6 7 8; 9] * @@ -104,7 +111,7 @@ function MPSKit.expectation_value( env.edges[WEST, r, c][14 15 16; 1] * peps[r, c][17; 3 7 11 15] * conj(peps[r, c][17; 4 8 12 16]) - + end o / n end end @@ -114,7 +121,37 @@ function MPSKit.expectation_value( ) return map(Iterators.product(axes(env.corners, 2), axes(env.corners, 3))) do (r, c) cnext = _next(c, size(peps, 2)) - o = @tensor opt = true env.corners[NORTHWEST, r, c][1; 3] * + o = @tensor order = ( + 28, + 24, + 23, + 16, + 25, + 22, + 26, + 27, + 17, + 21, + 4, + 1, + 3, + 5, + 7, + 8, + 9, + 2, + 6, + 10, + 14, + 19, + 15, + 13, + 31, + 32, + 29, + 30, + ) begin # physical spaces + env.corners[NORTHWEST, r, c][1; 3] * env.edges[NORTH, r, c][3 5 8; 13] * env.edges[NORTH, r, cnext][13 16 22; 23] * env.corners[NORTHEAST, r, cnext][23; 24] * @@ -129,8 +166,37 @@ function MPSKit.expectation_value( peps[r, cnext][30; 16 25 17 15] * conj(peps[r, cnext][32; 22 26 21 19]) * O.op[31 32; 29 30] - - n = @tensor opt = true env.corners[NORTHWEST, r, c][1; 3] * + end + + n = @tensor order = ( + 2, + 3, + 1, + 5, + 7, + 28, + 24, + 23, + 16, + 25, + 30, + 22, + 26, + 27, + 17, + 21, + 14, + 15, + 6, + 4, + 13, + 29, + 8, + 19, + 10, + 9, + ) begin + env.corners[NORTHWEST, r, c][1; 3] * env.edges[NORTH, r, c][3 5 8; 13] * env.edges[NORTH, r, cnext][13 16 22; 23] * env.corners[NORTHEAST, r, cnext][23; 24] * @@ -144,6 +210,7 @@ function MPSKit.expectation_value( conj(peps[r, c][29; 8 19 10 9]) * peps[r, cnext][30; 16 25 17 15] * conj(peps[r, cnext][30; 22 26 21 19]) + end o / n end end From 0ea08d6d21a72caac70734ad1c79788ccfdb9e57 Mon Sep 17 00:00:00 2001 From: leburgel Date: Wed, 19 Jun 2024 21:20:13 +0200 Subject: [PATCH 4/4] Locally disable formattting --- src/operators/localoperator.jl | 60 ++++------------------------------ 1 file changed, 6 insertions(+), 54 deletions(-) diff --git a/src/operators/localoperator.jl b/src/operators/localoperator.jl index ffc77c0d..346e3c8d 100644 --- a/src/operators/localoperator.jl +++ b/src/operators/localoperator.jl @@ -116,40 +116,15 @@ function MPSKit.expectation_value( end end +#! format: off function MPSKit.expectation_value( peps::InfinitePEPS, env, O::NLocalOperator{NearestNeighbor} ) return map(Iterators.product(axes(env.corners, 2), axes(env.corners, 3))) do (r, c) cnext = _next(c, size(peps, 2)) o = @tensor order = ( - 28, - 24, - 23, - 16, - 25, - 22, - 26, - 27, - 17, - 21, - 4, - 1, - 3, - 5, - 7, - 8, - 9, - 2, - 6, - 10, - 14, - 19, - 15, - 13, - 31, - 32, - 29, - 30, + 28, 24, 23, 16, 25, 22, 26, 27, 17, 21, 4, 1, 3, 5, 7, 8, 9, 2, 6, 10, 14, 19, + 15, 13, 31, 32, 29, 30, ) begin # physical spaces env.corners[NORTHWEST, r, c][1; 3] * env.edges[NORTH, r, c][3 5 8; 13] * @@ -169,32 +144,8 @@ function MPSKit.expectation_value( end n = @tensor order = ( - 2, - 3, - 1, - 5, - 7, - 28, - 24, - 23, - 16, - 25, - 30, - 22, - 26, - 27, - 17, - 21, - 14, - 15, - 6, - 4, - 13, - 29, - 8, - 19, - 10, - 9, + 2, 3, 1, 5, 7, 28, 24, 23, 16, 25, 30, 22, 26, 27, 17, 21, 14, 15, 6, 4, 13, 29, + 8, 19, 10, 9, ) begin env.corners[NORTHWEST, r, c][1; 3] * env.edges[NORTH, r, c][3 5 8; 13] * @@ -214,6 +165,7 @@ function MPSKit.expectation_value( o / n end end +#! format: on """ costfun(peps::InfinitePEPS, env, op::NLocalOperator{NearestNeighbor})