diff --git a/docs/src/changelog.md b/docs/src/changelog.md index c177aa005..f66e30fc8 100644 --- a/docs/src/changelog.md +++ b/docs/src/changelog.md @@ -25,6 +25,7 @@ When releasing a new version, move the "Unreleased" changes to a new version sec ### Changed - Bump OptimKit.jl compatibility to v0.4 +- Move `info.truncation_error` and `info.condition_number` into the `info.contraction_metrics` named tuple for `leading_boundary` and `fixedpoint` ### Deprecated diff --git a/docs/src/examples/heisenberg/index.md b/docs/src/examples/heisenberg/index.md index 298b2ffb9..f38960214 100644 --- a/docs/src/examples/heisenberg/index.md +++ b/docs/src/examples/heisenberg/index.md @@ -118,21 +118,23 @@ env₀, info_ctmrg = leading_boundary(env_random, peps₀; boundary_alg...); ```` [ Info: CTMRG init: obj = -2.749614463601e+00 +3.639628057806e+00im err = 1.0000e+00 -[ Info: CTMRG conv 27: obj = +9.727103564786e+00 err = 2.6201795901e-11 time = 7.98 sec +[ Info: CTMRG conv 27: obj = +9.727103564786e+00 err = 2.6201048445e-11 time = 0.34 sec ```` Besides the converged environment, `leading_boundary` also returns a `NamedTuple` of -informational quantities such as the last maximal truncation error - that is, the SVD -approximation error incurred in the last CTMRG iteration, maximized over all spatial -directions and unit cell entries: +informational quantities which contains, among other things, a `contraction_metric` tuple. +This may contain different quantities depending on the method of contraction, and for this +CTMRG variant we return the last maximal truncation error (the SVD approximation +error maximized over all spatial directions and unit cell entries) as well as the condition +number of the decomposition (the ratio of largest to smallest singular value): ````julia -@show info_ctmrg.truncation_error; +@show info_ctmrg.contraction_metrics; ```` ```` -info_ctmrg.truncation_error = 0.0008076332823860801 +info_ctmrg.contraction_metrics = (truncation_error = 0.00080763328242187, condition_number = 1.0752351780901926e10) ```` @@ -149,88 +151,88 @@ peps, env, E, info_opt = fixedpoint( ```` ```` -[ Info: LBFGS: initializing with f = 6.016453104343e-04, ‖∇f‖ = 9.3548e-01 -[ Info: LBFGS: iter 1, Δt 4.52 s: f = -4.897965192207e-01, ‖∇f‖ = 6.0022e-01, α = 5.94e+01, m = 0, nfg = 5 -[ Info: LBFGS: iter 2, Δt 1.55 s: f = -5.019846341173e-01, ‖∇f‖ = 5.3738e-01, α = 2.80e-01, m = 1, nfg = 2 -[ Info: LBFGS: iter 3, Δt 328.4 ms: f = -5.231639258984e-01, ‖∇f‖ = 3.9927e-01, α = 1.00e+00, m = 2, nfg = 1 -[ Info: LBFGS: iter 4, Δt 842.4 ms: f = -5.386543628560e-01, ‖∇f‖ = 4.1552e-01, α = 2.29e-01, m = 3, nfg = 2 -[ Info: LBFGS: iter 5, Δt 2.49 s: f = -5.498211821771e-01, ‖∇f‖ = 4.4002e-01, α = 6.90e-02, m = 4, nfg = 4 -[ Info: LBFGS: iter 6, Δt 850.0 ms: f = -5.690169518488e-01, ‖∇f‖ = 4.8450e-01, α = 2.26e-01, m = 5, nfg = 2 -[ Info: LBFGS: iter 7, Δt 325.7 ms: f = -5.871277303926e-01, ‖∇f‖ = 4.1970e-01, α = 1.00e+00, m = 6, nfg = 1 -[ Info: LBFGS: iter 8, Δt 319.8 ms: f = -6.001554483426e-01, ‖∇f‖ = 2.1792e-01, α = 1.00e+00, m = 7, nfg = 1 -[ Info: LBFGS: iter 9, Δt 305.8 ms: f = -6.068835686463e-01, ‖∇f‖ = 1.9566e-01, α = 1.00e+00, m = 8, nfg = 1 -[ Info: LBFGS: iter 10, Δt 276.9 ms: f = -6.250397748968e-01, ‖∇f‖ = 3.0330e-01, α = 1.00e+00, m = 9, nfg = 1 -[ Info: LBFGS: iter 11, Δt 282.8 ms: f = -6.391659645908e-01, ‖∇f‖ = 2.3075e-01, α = 1.00e+00, m = 10, nfg = 1 -[ Info: LBFGS: iter 12, Δt 392.4 ms: f = -6.471793388973e-01, ‖∇f‖ = 2.6051e-01, α = 1.00e+00, m = 11, nfg = 1 -[ Info: LBFGS: iter 13, Δt 724.4 ms: f = -6.503370671505e-01, ‖∇f‖ = 1.6112e-01, α = 1.00e+00, m = 12, nfg = 1 -[ Info: LBFGS: iter 14, Δt 322.8 ms: f = -6.546061020085e-01, ‖∇f‖ = 7.7751e-02, α = 1.00e+00, m = 13, nfg = 1 -[ Info: LBFGS: iter 15, Δt 237.3 ms: f = -6.559626422861e-01, ‖∇f‖ = 5.1323e-02, α = 1.00e+00, m = 14, nfg = 1 -[ Info: LBFGS: iter 16, Δt 261.0 ms: f = -6.570346071528e-01, ‖∇f‖ = 5.6661e-02, α = 1.00e+00, m = 15, nfg = 1 -[ Info: LBFGS: iter 17, Δt 263.3 ms: f = -6.586101879490e-01, ‖∇f‖ = 4.5250e-02, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 18, Δt 248.0 ms: f = -6.594209589994e-01, ‖∇f‖ = 4.8923e-02, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 19, Δt 263.4 ms: f = -6.595831316360e-01, ‖∇f‖ = 5.7833e-02, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 20, Δt 268.8 ms: f = -6.598106808006e-01, ‖∇f‖ = 1.7741e-02, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 21, Δt 256.8 ms: f = -6.598737940556e-01, ‖∇f‖ = 1.4673e-02, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 22, Δt 264.8 ms: f = -6.600721854328e-01, ‖∇f‖ = 1.9298e-02, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 23, Δt 254.1 ms: f = -6.602319074023e-01, ‖∇f‖ = 1.7538e-02, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 24, Δt 273.3 ms: f = -6.603792430521e-01, ‖∇f‖ = 2.3872e-02, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 25, Δt 263.2 ms: f = -6.604617775509e-01, ‖∇f‖ = 2.3385e-02, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 26, Δt 258.8 ms: f = -6.605536696759e-01, ‖∇f‖ = 1.2672e-02, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 27, Δt 257.1 ms: f = -6.606169735172e-01, ‖∇f‖ = 1.0506e-02, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 28, Δt 285.6 ms: f = -6.608141517158e-01, ‖∇f‖ = 1.8075e-02, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 29, Δt 305.3 ms: f = -6.609609491552e-01, ‖∇f‖ = 1.7508e-02, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 30, Δt 796.4 ms: f = -6.610389180525e-01, ‖∇f‖ = 1.1325e-02, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 31, Δt 328.4 ms: f = -6.610873060103e-01, ‖∇f‖ = 1.0269e-02, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 32, Δt 254.5 ms: f = -6.611212029182e-01, ‖∇f‖ = 8.8756e-03, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 33, Δt 281.7 ms: f = -6.611799456772e-01, ‖∇f‖ = 1.1435e-02, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 34, Δt 553.2 ms: f = -6.612071690766e-01, ‖∇f‖ = 8.8858e-03, α = 5.30e-01, m = 16, nfg = 2 -[ Info: LBFGS: iter 35, Δt 285.6 ms: f = -6.612262681103e-01, ‖∇f‖ = 6.4795e-03, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 36, Δt 295.0 ms: f = -6.612605080039e-01, ‖∇f‖ = 5.8879e-03, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 37, Δt 285.7 ms: f = -6.612675983705e-01, ‖∇f‖ = 1.2007e-02, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 38, Δt 278.1 ms: f = -6.612837466720e-01, ‖∇f‖ = 4.9256e-03, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 39, Δt 275.6 ms: f = -6.612924155095e-01, ‖∇f‖ = 4.6090e-03, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 40, Δt 273.9 ms: f = -6.613078556647e-01, ‖∇f‖ = 6.2724e-03, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 41, Δt 282.3 ms: f = -6.613407946569e-01, ‖∇f‖ = 8.9187e-03, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 42, Δt 293.4 ms: f = -6.614147324894e-01, ‖∇f‖ = 1.6921e-02, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 43, Δt 310.8 ms: f = -6.614896605795e-01, ‖∇f‖ = 2.7701e-02, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 44, Δt 289.7 ms: f = -6.616600115097e-01, ‖∇f‖ = 2.0288e-02, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 45, Δt 377.8 ms: f = -6.618744649549e-01, ‖∇f‖ = 2.2589e-02, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 46, Δt 739.3 ms: f = -6.619293873126e-01, ‖∇f‖ = 2.6087e-02, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 47, Δt 320.0 ms: f = -6.620580680546e-01, ‖∇f‖ = 1.8561e-02, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 48, Δt 607.9 ms: f = -6.621418094892e-01, ‖∇f‖ = 2.1694e-02, α = 5.08e-01, m = 16, nfg = 2 -[ Info: LBFGS: iter 49, Δt 299.7 ms: f = -6.622424140119e-01, ‖∇f‖ = 1.4693e-02, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 50, Δt 317.6 ms: f = -6.623561643274e-01, ‖∇f‖ = 1.5643e-02, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 51, Δt 325.3 ms: f = -6.624189189954e-01, ‖∇f‖ = 1.2526e-02, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 52, Δt 322.8 ms: f = -6.624484647013e-01, ‖∇f‖ = 7.7875e-03, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 53, Δt 302.8 ms: f = -6.624620825387e-01, ‖∇f‖ = 7.2801e-03, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 54, Δt 297.0 ms: f = -6.624761506291e-01, ‖∇f‖ = 5.6893e-03, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 55, Δt 302.8 ms: f = -6.624920797996e-01, ‖∇f‖ = 7.4763e-03, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 56, Δt 618.9 ms: f = -6.624974230146e-01, ‖∇f‖ = 3.9289e-03, α = 5.46e-01, m = 16, nfg = 2 -[ Info: LBFGS: iter 57, Δt 288.3 ms: f = -6.624993982624e-01, ‖∇f‖ = 3.0506e-03, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 58, Δt 284.2 ms: f = -6.625033254432e-01, ‖∇f‖ = 2.2061e-03, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 59, Δt 300.0 ms: f = -6.625068780651e-01, ‖∇f‖ = 2.0862e-03, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 60, Δt 812.0 ms: f = -6.625094238841e-01, ‖∇f‖ = 3.0782e-03, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 61, Δt 314.7 ms: f = -6.625108313560e-01, ‖∇f‖ = 1.9160e-03, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 62, Δt 248.5 ms: f = -6.625115537204e-01, ‖∇f‖ = 8.6226e-04, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 63, Δt 261.4 ms: f = -6.625118952372e-01, ‖∇f‖ = 7.1198e-04, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 64, Δt 273.4 ms: f = -6.625122637335e-01, ‖∇f‖ = 6.9776e-04, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 65, Δt 263.1 ms: f = -6.625125878909e-01, ‖∇f‖ = 1.1757e-03, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 66, Δt 278.5 ms: f = -6.625129012017e-01, ‖∇f‖ = 6.1076e-04, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 67, Δt 275.1 ms: f = -6.625131620795e-01, ‖∇f‖ = 6.7509e-04, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 68, Δt 287.4 ms: f = -6.625134659017e-01, ‖∇f‖ = 7.4076e-04, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 69, Δt 585.2 ms: f = -6.625136173027e-01, ‖∇f‖ = 1.0650e-03, α = 4.63e-01, m = 16, nfg = 2 -[ Info: LBFGS: iter 70, Δt 297.3 ms: f = -6.625138093900e-01, ‖∇f‖ = 5.3214e-04, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 71, Δt 267.8 ms: f = -6.625138941594e-01, ‖∇f‖ = 4.9455e-04, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 72, Δt 275.5 ms: f = -6.625139584721e-01, ‖∇f‖ = 4.6079e-04, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 73, Δt 270.4 ms: f = -6.625140156102e-01, ‖∇f‖ = 3.5058e-04, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 74, Δt 280.5 ms: f = -6.625140884579e-01, ‖∇f‖ = 7.7069e-04, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 75, Δt 282.6 ms: f = -6.625141400523e-01, ‖∇f‖ = 6.5839e-04, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 76, Δt 267.8 ms: f = -6.625141806040e-01, ‖∇f‖ = 3.1793e-04, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 77, Δt 822.8 ms: f = -6.625142155106e-01, ‖∇f‖ = 2.0830e-04, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 78, Δt 263.1 ms: f = -6.625142398464e-01, ‖∇f‖ = 1.8962e-04, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 79, Δt 253.8 ms: f = -6.625142606414e-01, ‖∇f‖ = 2.6019e-04, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: iter 80, Δt 262.8 ms: f = -6.625142658376e-01, ‖∇f‖ = 2.4559e-04, α = 1.00e+00, m = 16, nfg = 1 -[ Info: LBFGS: converged after 81 iterations and time 5.83 m: f = -6.625142736963e-01, ‖∇f‖ = 9.4632e-05 +[ Info: LBFGS: initializing with f = 6.016453104372e-04, ‖∇f‖ = 9.3548e-01 +[ Info: LBFGS: iter 1, Δt 5.62 s: f = -4.897965201565e-01, ‖∇f‖ = 6.0022e-01, α = 5.94e+01, m = 0, nfg = 5 +[ Info: LBFGS: iter 2, Δt 1.04 s: f = -5.019846351509e-01, ‖∇f‖ = 5.3738e-01, α = 2.80e-01, m = 1, nfg = 2 +[ Info: LBFGS: iter 3, Δt 342.4 ms: f = -5.231639268904e-01, ‖∇f‖ = 3.9927e-01, α = 1.00e+00, m = 2, nfg = 1 +[ Info: LBFGS: iter 4, Δt 747.3 ms: f = -5.386543630134e-01, ‖∇f‖ = 4.1552e-01, α = 2.29e-01, m = 3, nfg = 2 +[ Info: LBFGS: iter 5, Δt 2.15 s: f = -5.498211740486e-01, ‖∇f‖ = 4.4002e-01, α = 6.90e-02, m = 4, nfg = 4 +[ Info: LBFGS: iter 6, Δt 922.3 ms: f = -5.690169637654e-01, ‖∇f‖ = 4.8450e-01, α = 2.26e-01, m = 5, nfg = 2 +[ Info: LBFGS: iter 7, Δt 342.6 ms: f = -5.871277574299e-01, ‖∇f‖ = 4.1970e-01, α = 1.00e+00, m = 6, nfg = 1 +[ Info: LBFGS: iter 8, Δt 1.27 s: f = -6.001554858779e-01, ‖∇f‖ = 2.1792e-01, α = 1.00e+00, m = 7, nfg = 1 +[ Info: LBFGS: iter 9, Δt 334.8 ms: f = -6.068836018580e-01, ‖∇f‖ = 1.9566e-01, α = 1.00e+00, m = 8, nfg = 1 +[ Info: LBFGS: iter 10, Δt 330.7 ms: f = -6.250397688400e-01, ‖∇f‖ = 3.0330e-01, α = 1.00e+00, m = 9, nfg = 1 +[ Info: LBFGS: iter 11, Δt 251.4 ms: f = -6.391660376636e-01, ‖∇f‖ = 2.3075e-01, α = 1.00e+00, m = 10, nfg = 1 +[ Info: LBFGS: iter 12, Δt 267.4 ms: f = -6.471796195686e-01, ‖∇f‖ = 2.6051e-01, α = 1.00e+00, m = 11, nfg = 1 +[ Info: LBFGS: iter 13, Δt 226.5 ms: f = -6.503370025252e-01, ‖∇f‖ = 1.6112e-01, α = 1.00e+00, m = 12, nfg = 1 +[ Info: LBFGS: iter 14, Δt 254.5 ms: f = -6.546061095107e-01, ‖∇f‖ = 7.7752e-02, α = 1.00e+00, m = 13, nfg = 1 +[ Info: LBFGS: iter 15, Δt 266.9 ms: f = -6.559626479096e-01, ‖∇f‖ = 5.1323e-02, α = 1.00e+00, m = 14, nfg = 1 +[ Info: LBFGS: iter 16, Δt 267.1 ms: f = -6.570345925072e-01, ‖∇f‖ = 5.6663e-02, α = 1.00e+00, m = 15, nfg = 1 +[ Info: LBFGS: iter 17, Δt 260.7 ms: f = -6.586101542992e-01, ‖∇f‖ = 4.5249e-02, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 18, Δt 273.4 ms: f = -6.594210783037e-01, ‖∇f‖ = 4.8908e-02, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 19, Δt 270.6 ms: f = -6.595829407862e-01, ‖∇f‖ = 5.7868e-02, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 20, Δt 261.5 ms: f = -6.598106978631e-01, ‖∇f‖ = 1.7743e-02, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 21, Δt 267.3 ms: f = -6.598737919822e-01, ‖∇f‖ = 1.4674e-02, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 22, Δt 256.5 ms: f = -6.600722399901e-01, ‖∇f‖ = 1.9297e-02, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 23, Δt 264.3 ms: f = -6.602319320307e-01, ‖∇f‖ = 1.7537e-02, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 24, Δt 264.5 ms: f = -6.603792234693e-01, ‖∇f‖ = 2.3875e-02, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 25, Δt 276.0 ms: f = -6.604618342679e-01, ‖∇f‖ = 2.3372e-02, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 26, Δt 1.23 s: f = -6.605536670251e-01, ‖∇f‖ = 1.2672e-02, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 27, Δt 267.2 ms: f = -6.606170020178e-01, ‖∇f‖ = 1.0507e-02, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 28, Δt 298.9 ms: f = -6.608142109072e-01, ‖∇f‖ = 1.8082e-02, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 29, Δt 328.6 ms: f = -6.609609278098e-01, ‖∇f‖ = 1.7516e-02, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 30, Δt 249.0 ms: f = -6.610389074905e-01, ‖∇f‖ = 1.1313e-02, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 31, Δt 266.7 ms: f = -6.610872582358e-01, ‖∇f‖ = 1.0263e-02, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 32, Δt 243.8 ms: f = -6.611211815134e-01, ‖∇f‖ = 8.8770e-03, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 33, Δt 273.6 ms: f = -6.611798467656e-01, ‖∇f‖ = 1.1488e-02, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 34, Δt 589.4 ms: f = -6.612071948177e-01, ‖∇f‖ = 8.8666e-03, α = 5.31e-01, m = 16, nfg = 2 +[ Info: LBFGS: iter 35, Δt 312.8 ms: f = -6.612262742065e-01, ‖∇f‖ = 6.4670e-03, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 36, Δt 309.1 ms: f = -6.612605505781e-01, ‖∇f‖ = 5.8761e-03, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 37, Δt 296.5 ms: f = -6.612675206044e-01, ‖∇f‖ = 1.2105e-02, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 38, Δt 311.6 ms: f = -6.612838274236e-01, ‖∇f‖ = 4.9173e-03, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 39, Δt 297.0 ms: f = -6.612924065028e-01, ‖∇f‖ = 4.5918e-03, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 40, Δt 302.3 ms: f = -6.613079391530e-01, ‖∇f‖ = 6.2780e-03, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 41, Δt 309.7 ms: f = -6.613408205522e-01, ‖∇f‖ = 8.9067e-03, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 42, Δt 310.3 ms: f = -6.614138147418e-01, ‖∇f‖ = 1.7166e-02, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 43, Δt 340.2 ms: f = -6.614875520889e-01, ‖∇f‖ = 2.7427e-02, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 44, Δt 373.1 ms: f = -6.616598996952e-01, ‖∇f‖ = 1.9056e-02, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 45, Δt 399.3 ms: f = -6.618786556444e-01, ‖∇f‖ = 2.2180e-02, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 46, Δt 1.39 s: f = -6.619400903666e-01, ‖∇f‖ = 2.5707e-02, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 47, Δt 319.4 ms: f = -6.620475837462e-01, ‖∇f‖ = 1.8971e-02, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 48, Δt 415.2 ms: f = -6.621064283010e-01, ‖∇f‖ = 3.7601e-02, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 49, Δt 402.7 ms: f = -6.622530651429e-01, ‖∇f‖ = 1.3384e-02, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 50, Δt 335.8 ms: f = -6.623266509915e-01, ‖∇f‖ = 1.1681e-02, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 51, Δt 368.6 ms: f = -6.623900625629e-01, ‖∇f‖ = 1.0879e-02, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 52, Δt 400.5 ms: f = -6.624417840065e-01, ‖∇f‖ = 1.3536e-02, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 53, Δt 843.4 ms: f = -6.624657232439e-01, ‖∇f‖ = 8.4312e-03, α = 4.80e-01, m = 16, nfg = 2 +[ Info: LBFGS: iter 54, Δt 417.5 ms: f = -6.624781165452e-01, ‖∇f‖ = 5.0930e-03, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 55, Δt 420.6 ms: f = -6.624880687095e-01, ‖∇f‖ = 5.2557e-03, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 56, Δt 407.4 ms: f = -6.624977042182e-01, ‖∇f‖ = 3.7286e-03, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 57, Δt 452.2 ms: f = -6.625008746110e-01, ‖∇f‖ = 3.0276e-03, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 58, Δt 407.0 ms: f = -6.625030255855e-01, ‖∇f‖ = 2.4305e-03, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 59, Δt 404.5 ms: f = -6.625070516495e-01, ‖∇f‖ = 2.1048e-03, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 60, Δt 416.0 ms: f = -6.625095242229e-01, ‖∇f‖ = 2.1471e-03, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 61, Δt 815.1 ms: f = -6.625106856424e-01, ‖∇f‖ = 1.7835e-03, α = 5.47e-01, m = 16, nfg = 2 +[ Info: LBFGS: iter 62, Δt 375.8 ms: f = -6.625114666348e-01, ‖∇f‖ = 9.0132e-04, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 63, Δt 367.3 ms: f = -6.625118764288e-01, ‖∇f‖ = 8.0255e-04, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 64, Δt 1.29 s: f = -6.625122687065e-01, ‖∇f‖ = 9.0615e-04, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 65, Δt 274.7 ms: f = -6.625126290506e-01, ‖∇f‖ = 8.0460e-04, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 66, Δt 337.3 ms: f = -6.625129211222e-01, ‖∇f‖ = 6.8501e-04, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 67, Δt 360.9 ms: f = -6.625132419353e-01, ‖∇f‖ = 9.0265e-04, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 68, Δt 310.6 ms: f = -6.625134633026e-01, ‖∇f‖ = 7.9160e-04, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 69, Δt 311.3 ms: f = -6.625136591289e-01, ‖∇f‖ = 5.0828e-04, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 70, Δt 324.8 ms: f = -6.625138308035e-01, ‖∇f‖ = 7.9904e-04, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 71, Δt 658.4 ms: f = -6.625138950807e-01, ‖∇f‖ = 4.3784e-04, α = 5.13e-01, m = 16, nfg = 2 +[ Info: LBFGS: iter 72, Δt 330.0 ms: f = -6.625139324941e-01, ‖∇f‖ = 3.5191e-04, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 73, Δt 377.8 ms: f = -6.625140365412e-01, ‖∇f‖ = 2.7327e-04, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 74, Δt 674.0 ms: f = -6.625140701012e-01, ‖∇f‖ = 7.1588e-04, α = 4.32e-01, m = 16, nfg = 2 +[ Info: LBFGS: iter 75, Δt 346.5 ms: f = -6.625141329298e-01, ‖∇f‖ = 4.5959e-04, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 76, Δt 343.8 ms: f = -6.625141933640e-01, ‖∇f‖ = 2.3876e-04, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 77, Δt 343.9 ms: f = -6.625142295649e-01, ‖∇f‖ = 1.7163e-04, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 78, Δt 342.5 ms: f = -6.625142520304e-01, ‖∇f‖ = 1.3279e-04, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 79, Δt 349.1 ms: f = -6.625142665992e-01, ‖∇f‖ = 2.8569e-04, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: iter 80, Δt 329.9 ms: f = -6.625142803082e-01, ‖∇f‖ = 1.2759e-04, α = 1.00e+00, m = 16, nfg = 1 +[ Info: LBFGS: converged after 81 iterations and time 6.94 m: f = -6.625142855970e-01, ‖∇f‖ = 7.7033e-05 ```` @@ -244,8 +246,8 @@ the convergence rate: ```` ```` -info_opt.fg_evaluations = 96 -info_opt.gradnorms[1:10:end] = [0.9354752030131099, 0.3033019277899899, 0.017741463681835545, 0.01132472701425422, 0.006272379430806119, 0.015643014849711687, 0.003078240790192421, 0.000532137892512568, 0.0002455878974975024] +info_opt.fg_evaluations = 97 +info_opt.gradnorms[1:10:end] = [0.9354752017271177, 0.3033034076782405, 0.017742662111911257, 0.011312825498690943, 0.0062779819357426676, 0.011680613608174078, 0.0021471423320920044, 0.0007990427093226254, 0.0001275947945785803] ```` @@ -258,7 +260,7 @@ $E_{\text{ref}}=−0.6694421$. From our simple optimization we find: ```` ```` -E = -0.6625142736962993 +E = -0.6625142855969753 ```` @@ -285,8 +287,8 @@ correlation lengths and transfer matrix spectra for all unit cell coordinates: ```` ```` -ξ_h = [1.0345801030391306] -ξ_v = [1.0245361358882241] +ξ_h = [1.0343404931444404] +ξ_v = [1.0242351103541054] ```` @@ -304,7 +306,10 @@ need to define the observable as a `TensorMap`: 2←2 TensorMap{Float64, TensorKit.ComplexSpace, 1, 1, Vector{Float64}}: codomain: ⊗(ℂ^2) domain: ⊗(ℂ^2) - + blocks: + * Trivial() => 2×2 reshape(view(::Vector{Float64}, 1:4), 2, 2) with eltype Float64: + 1.0 0.0 + 0.0 -1.0 ```` In order to be able to contract it with the PEPS and environment, we define need to define a @@ -328,7 +333,7 @@ Finally, to evaluate the expecation value on the `LocalOperator`, we call: ```` ```` -expectation_value(peps, M, env) = -0.7533445046064892 - 1.5265566588595902e-16im +expectation_value(peps, M, env) = -0.7532893440072446 - 4.85722573273506e-17im ```` diff --git a/docs/src/examples/heisenberg/main.ipynb b/docs/src/examples/heisenberg/main.ipynb index a1731e7f4..54fb6f083 100644 --- a/docs/src/examples/heisenberg/main.ipynb +++ b/docs/src/examples/heisenberg/main.ipynb @@ -204,9 +204,11 @@ "cell_type": "markdown", "source": [ "Besides the converged environment, `leading_boundary` also returns a `NamedTuple` of\n", - "informational quantities such as the last maximal truncation error - that is, the SVD\n", - "approximation error incurred in the last CTMRG iteration, maximized over all spatial\n", - "directions and unit cell entries:" + "informational quantities which contains, among other things, a `contraction_metric` tuple.\n", + "This may contain different quantities depending on the method of contraction, and for this\n", + "CTMRG variant we return the last maximal truncation error (the SVD approximation\n", + "error maximized over all spatial directions and unit cell entries) as well as the condition\n", + "number of the decomposition (the ratio of largest to smallest singular value):" ], "metadata": {} }, @@ -214,7 +216,7 @@ "outputs": [], "cell_type": "code", "source": [ - "@show info_ctmrg.truncation_error;" + "@show info_ctmrg.contraction_metrics;" ], "metadata": {}, "execution_count": null @@ -382,11 +384,11 @@ "file_extension": ".jl", "mimetype": "application/julia", "name": "julia", - "version": "1.11.7" + "version": "1.12.5" }, "kernelspec": { - "name": "julia-1.11", - "display_name": "Julia 1.11.7", + "name": "julia-1.12", + "display_name": "Julia 1.12.5", "language": "julia" } }, diff --git a/examples/Cache.toml b/examples/Cache.toml index 195db707d..f0e59d007 100644 --- a/examples/Cache.toml +++ b/examples/Cache.toml @@ -7,4 +7,4 @@ heisenberg_su = "3eb8556d949c0e47e39c679e9e438bc04d3e2a3ffe73e0a682963b37b05f9e9 xxz = "0231f0c1af2013e8edd9e5c192b108e1ab19a7dca22251c3bde525e3eee2a6aa" fermi_hubbard = "4997680c826e555557c661e605e1d7d363e0cee15522d0895fa0cfd53b1de001" j1j2_su = "c00fd13c0be323ab5825af59f3e7b31c3e51d3f65211d3836657b64274504c1c" -heisenberg = "d610c92223d41e296348f9858fab52eacbfe2a578f64f4f8ac4c70d486fb4da2" +heisenberg = "80bb9cc57ed85297b1b789a6c5f09494dac81b23631f48c6600ede9424c5d248" diff --git a/examples/heisenberg/main.jl b/examples/heisenberg/main.jl index d2dfbecfb..3f0139126 100644 --- a/examples/heisenberg/main.jl +++ b/examples/heisenberg/main.jl @@ -102,12 +102,14 @@ env₀, info_ctmrg = leading_boundary(env_random, peps₀; boundary_alg...); md""" Besides the converged environment, `leading_boundary` also returns a `NamedTuple` of -informational quantities such as the last maximal truncation error - that is, the SVD -approximation error incurred in the last CTMRG iteration, maximized over all spatial -directions and unit cell entries: +informational quantities which contains, among other things, a `contraction_metric` tuple. +This may contain different quantities depending on the method of contraction, and for this +CTMRG variant we return the last maximal truncation error (the SVD approximation +error maximized over all spatial directions and unit cell entries) as well as the condition +number of the decomposition (the ratio of largest to smallest singular value): """ -@show info_ctmrg.truncation_error; +@show info_ctmrg.contraction_metrics; md""" ## Ground state search diff --git a/src/algorithms/ctmrg/c4v.jl b/src/algorithms/ctmrg/c4v.jl index 9aaec610f..82a30dbbf 100644 --- a/src/algorithms/ctmrg/c4v.jl +++ b/src/algorithms/ctmrg/c4v.jl @@ -86,8 +86,7 @@ $(TYPEDFIELDS) C4vQRProjector(; kwargs...) -Construct the C₄ᵥ `qr`-based projector algorithm -based on the following keyword arguments: +Construct the C₄ᵥ `qr`-based projector algorithm based on the following keyword arguments: * `decomposition_alg=QRAdjoint()` : `left_orth` algorithm including the reverse rule. See [`QRAdjoint`](@ref). """ @@ -104,7 +103,7 @@ PROJECTOR_SYMBOLS[:c4v_qr] = C4vQRProjector _set_truncation(alg::C4vQRProjector, ::TruncationStrategy) = alg function check_input( - network::InfiniteSquareNetwork, env::CTMRGEnv, alg::C4vCTMRG; atol = 1.0e-10 + ::typeof(leading_boundary), network::InfiniteSquareNetwork, env::CTMRGEnv, alg::C4vCTMRG; atol = 1.0e-10 ) # check unit cell size length(network) == 1 || throw(ArgumentError("C4v CTMRG is only compatible with single-site unit cells.")) @@ -144,6 +143,10 @@ function ctmrg_iteration( enlarged_corner = c4v_enlarge(network, env, alg.projector_alg) corner′, projector, info = c4v_projector!(enlarged_corner, alg.projector_alg) edge′ = c4v_renormalize_edge(network, env, projector) + info = (; + contraction_metrics = (; info.truncation_error, info.condition_number), + info.D, info.V, info.D_full, info.V_full, info.truncation_indices, + ) return CTMRGEnv(corner′, edge′), info end function ctmrg_iteration( @@ -155,6 +158,7 @@ function ctmrg_iteration( projector, info = c4v_projector!(enlarged_corner, alg.projector_alg) edge′ = c4v_renormalize_edge(network, env, projector) corner′ = c4v_qr_renormalize_corner(edge′, projector, info.R) + info = (; contraction_metrics = (;), info.Q, info.R) return CTMRGEnv(corner′, edge′), info end diff --git a/src/algorithms/ctmrg/ctmrg.jl b/src/algorithms/ctmrg/ctmrg.jl index 7d30f5cd7..839e32a43 100644 --- a/src/algorithms/ctmrg/ctmrg.jl +++ b/src/algorithms/ctmrg/ctmrg.jl @@ -44,14 +44,6 @@ Perform a single CTMRG iteration in which all directions are being grown and ren """ function ctmrg_iteration(network, env, alg::CTMRGAlgorithm) end -""" - check_input(network, env, alg::CTMRGAlgorithm) - -Check compatibility of a given network and environment with a specified CTMRG algorithm. -""" -function check_input(network, env, alg::CTMRGAlgorithm) end -@non_differentiable check_input(args...) - """ leading_boundary(env₀, network; kwargs...) -> env, info # expert version: @@ -91,30 +83,15 @@ supplied via the keyword arguments or directly as an [`CTMRGAlgorithm`](@ref) st * `projector_alg::Symbol=:$(Defaults.projector_alg)` : Variant of the projector algorithm. See also [`ProjectorAlgorithm`](@ref). - `:halfinfinite` : Projection via SVDs of half-infinite (two enlarged corners) CTMRG environments. - `:fullinfinite` : Projection via SVDs of full-infinite (all four enlarged corners) CTMRG environments. - - `:c4v_eigh` : Projection via `eigh` of the Hermitian enlarged corner. + - `:c4v_eigh` : Projection via `eigh` of the Hermitian enlarged corner, works only for [`C4vCTMRG`](@ref). + - `:c4v_qr` : Projection via QR decomposition of the lower-rank column-enlarged corner, works only for [`C4vCTMRG`](@ref). ## Return values -The CTMRG routine returns the final CTMRG environment as well as an information `NamedTuple` -containing the following fields: - -* `truncation_error` : Last (maximal) SVD truncation error of the CTMRG projectors. -* `condition_number` : Last (maximal) condition number of the enlarged CTMRG environment. - -In case the `alg` is a `SimultaneousCTMRG`, the last SVD will also be returned: - -* `U` : Last unit cell of left singular vectors. -* `S` : Last unit cell of singular values. -* `V` : Last unit cell of right singular vectors. - -If, in addition, the specified SVD algorithm computes the full, untruncated SVD, the full -set of vectors and values will be returned as well: - -* `U_full` : Last unit cell of all left singular vectors. -* `S_full` : Last unit cell of all singular values. -* `V_full` : Last unit cell of all right singular vectors. - -For `C4vCTMRG` instead the last eigendecomposition `V` and `D` (and `V_full`, `D_full`) will be returned. +The `leading_boundary` routine returns the final environment as well as an information `NamedTuple` +that generally contains a `contraction_metrics` `NamedTuple` storing different contents depending +on the chosen `alg`. Depending on the contraction method, the information tuple may also contain +the final tensor decomposition (used in the projectors) including its truncation indices. """ function leading_boundary(env₀::CTMRGEnv, network::InfiniteSquareNetwork; kwargs...) alg = select_algorithm(leading_boundary, env₀; kwargs...) @@ -123,7 +100,7 @@ end function leading_boundary( env₀::CTMRGEnv, network::InfiniteSquareNetwork, alg::CTMRGAlgorithm ) - check_input(network, env₀, alg) + check_input(leading_boundary, network, env₀, alg) log = ignore_derivatives(() -> MPSKit.IterLog("CTMRG")) return LoggingExtras.withlevel(; alg.verbosity) do env = deepcopy(env₀) @@ -154,6 +131,14 @@ function leading_boundary(env₀::CTMRGEnv, state, args...; kwargs...) return leading_boundary(env₀, InfiniteSquareNetwork(state), args...; kwargs...) end +""" + check_input(::typeof(leading_boundary), network, env, alg::CTMRGAlgorithm) + +Check compatibility of a given network and environment with a specified CTMRG algorithm. +""" +function check_input(::typeof(leading_boundary), network, env, alg::CTMRGAlgorithm) end +@non_differentiable check_input(args...) + # custom CTMRG logging function ctmrg_loginit!(log, η, network, env) return @infov 2 loginit!(log, η, network_value(network, env)) diff --git a/src/algorithms/ctmrg/sequential.jl b/src/algorithms/ctmrg/sequential.jl index 1c9631675..9c858d36d 100644 --- a/src/algorithms/ctmrg/sequential.jl +++ b/src/algorithms/ctmrg/sequential.jl @@ -69,7 +69,7 @@ function ctmrg_iteration(network, env::CTMRGEnv, alg::SequentialCTMRG) network = rotate_north(network, EAST) env = rotate_north(env, EAST) end - return env, (; truncation_error, condition_number) + return env, (; contraction_metrics = (; truncation_error, condition_number)) end """ diff --git a/src/algorithms/ctmrg/simultaneous.jl b/src/algorithms/ctmrg/simultaneous.jl index 928246738..7e1fafb00 100644 --- a/src/algorithms/ctmrg/simultaneous.jl +++ b/src/algorithms/ctmrg/simultaneous.jl @@ -48,6 +48,10 @@ function ctmrg_iteration(network, env::CTMRGEnv, alg::SimultaneousCTMRG) end # expand environment projectors, info = simultaneous_projectors(enlarged_corners, env, alg.projector_alg) # compute projectors on all coordinates env′ = renormalize_simultaneously(enlarged_corners, projectors, network, env) # renormalize enlarged corners + info = (; + contraction_metrics = (; info.truncation_error, info.condition_number), + info.U, info.S, info.V, info.U_full, info.S_full, info.V_full, info.truncation_indices, + ) return env′, info end diff --git a/src/algorithms/optimization/fixed_point_differentiation.jl b/src/algorithms/optimization/fixed_point_differentiation.jl index faf25c04d..b5c47f979 100644 --- a/src/algorithms/optimization/fixed_point_differentiation.jl +++ b/src/algorithms/optimization/fixed_point_differentiation.jl @@ -201,13 +201,19 @@ EigSolver(; kwargs...) = GradMode(; alg = :eigsolver, kwargs...) GRADIENT_MODE_SYMBOLS[:eigsolver] = EigSolver """ - _check_algorithm_combination(boundary_alg, gradient_alg) + _check_algorithm_combination(boundary_alg, gradient_alg_or_symmetrization) + _check_algorithm_combination(boundary_alg, gradient_alg, symmetrization) Check for allowed combinations of gradient algorithm and boundary algorithm to be used for computing the gradient of a `leading_boundary` call. Throws an error containing a recommended fix if the combination is not allowed or broken. """ -function _check_algorithm_combination(boundary_alg, gradient_alg) end +function _check_algorithm_combination(boundary_alg, gradient_alg_or_symmetrization) end +function _check_algorithm_combination(boundary_alg, gradient_alg, symmetrization) + _check_algorithm_combination(boundary_alg, gradient_alg) + _check_algorithm_combination(boundary_alg, symmetrization) + return nothing +end function _check_algorithm_combination(::SequentialCTMRG, ::GradMode{:fixed}) msg = "`:fixed` mode is not compatible with `SequentialCTMRG` since the sequential \ application of SVDs does not allow to differentiate through a fixed set of \ @@ -216,10 +222,18 @@ function _check_algorithm_combination(::SequentialCTMRG, ::GradMode{:fixed}) end function _check_algorithm_combination(::C4vCTMRG{<:C4vEighProjector}, ::GradMode{:diffgauge}) msg = "`:diffgauge` mode is currently not compatible with eigh-based C4v CTMRG; \ - either switch to a different projector algorithm (e.g. `c4v_qr`), or use :fixed \ - mode for differentiation instead." + either switch to a different projector algorithm (e.g. `c4v_qr`), or use :fixed \ + mode for differentiation instead." throw(ArgumentError(msg)) end +function _check_algorithm_combination(::C4vCTMRG, symm::Union{Nothing, <:SymmetrizationStyle}) + if !(symm isa RotateReflect) + msg = "C4vCTMRG optimization is compatible only with RotateReflect symmetrization. \ + Make sure to set `symmetrization = RotateReflect()`." + throw(ArgumentError(msg)) + end + return nothing +end #= Evaluating the gradient of the cost function for CTMRG: diff --git a/src/algorithms/optimization/peps_optimization.jl b/src/algorithms/optimization/peps_optimization.jl index 73dd5672b..db9acb72a 100644 --- a/src/algorithms/optimization/peps_optimization.jl +++ b/src/algorithms/optimization/peps_optimization.jl @@ -14,25 +14,25 @@ $(TYPEDFIELDS) Construct a PEPS optimization algorithm struct based on keyword arguments. For a full description, see [`fixedpoint`](@ref). The supported keywords are: -* `boundary_alg::Union{NamedTuple,<:CTMRGAlgorithm}` +* `boundary_alg::Union{NamedTuple,<:CTMRGAlgorithm,...}` * `gradient_alg::Union{NamedTuple,Nothing,<:GradMode}` * `optimizer_alg::Union{NamedTuple,<:OptimKit.OptimizationAlgorithm}` * `reuse_env::Bool=$(Defaults.reuse_env)` * `symmetrization::Union{Nothing,SymmetrizationStyle}=nothing` """ -struct PEPSOptimize{G} - boundary_alg::CTMRGAlgorithm +struct PEPSOptimize{B, G} + boundary_alg::B gradient_alg::G optimizer_alg::OptimKit.OptimizationAlgorithm reuse_env::Bool symmetrization::Union{Nothing, SymmetrizationStyle} function PEPSOptimize( # Inner constructor to prohibit illegal setting combinations - boundary_alg::CTMRGAlgorithm, gradient_alg::G, optimizer_alg, + boundary_alg::B, gradient_alg::G, optimizer_alg, reuse_env, symmetrization, - ) where {G} - _check_algorithm_combination(boundary_alg, gradient_alg) - return new{G}(boundary_alg, gradient_alg, optimizer_alg, reuse_env, symmetrization) + ) where {B, G} + _check_algorithm_combination(boundary_alg, gradient_alg, symmetrization) + return new{B, G}(boundary_alg, gradient_alg, optimizer_alg, reuse_env, symmetrization) end end @@ -85,13 +85,13 @@ function _OptimizationAlgorithm(; end """ - fixedpoint(operator, peps₀::InfinitePEPS, env₀::CTMRGEnv; kwargs...) -> peps_final, env_final, cost_final, info + fixedpoint(operator, peps₀::InfinitePEPS, env₀; kwargs...) -> peps_final, env_final, cost_final, info # expert version: - fixedpoint(operator, peps₀::InfinitePEPS, env₀::CTMRGEnv, alg::PEPSOptimize; finalize!=OptimKit._finalize!) + fixedpoint(operator, peps₀::InfinitePEPS, env₀, alg::PEPSOptimize; finalize!=OptimKit._finalize!) Find the fixed point of `operator` (i.e. the ground state) starting from `peps₀` according to the supplied optimization parameters. The initial environment `env₀` serves as an -initial guess for the first CTMRG run. By default, a random initial environment is used. +initial guess for the first boundary contraction run. By default, a random initial environment is used. The optimization parameters can be supplied via the keyword arguments or directly as a `PEPSOptimize` struct. The following keyword arguments are supported: @@ -113,8 +113,8 @@ The optimization parameters can be supplied via the keyword arguments or directl ### Boundary algorithm -Supply boundary algorithm parameters via `boundary_alg::Union{NamedTuple,<:CTMRGAlgorithm}` -using either a `NamedTuple` of keyword arguments or a `CTMRGAlgorithm` directly. +Supply boundary algorithm parameters via `boundary_alg` +using either a `NamedTuple` of keyword arguments or a boundary algorithm instance directly. See [`leading_boundary`](@ref) for a description of all possible keyword arguments. By default, a CTMRG tolerance of `tol=1e-4tol` and is used. @@ -165,22 +165,22 @@ information `NamedTuple` which contains the following entries: * `fg_evaluations` : Number of evaluations of the cost and gradient function. * `costs` : History of cost values. * `gradnorms` : History of gradient norms. -* `truncation_errors` : History of maximal truncation errors of the boundary algorithm. -* `condition_numbers` : History of maximal condition numbers of the CTMRG environments. +* `contraction_metrics` : History of boundary-algorithm-specific contraction information, e.g. truncation errors and condition numbers. * `gradnorms_unitcell` : History of gradient norms for each respective unit cell entry. * `times` : History of optimization step execution times. """ function fixedpoint( - operator, peps₀::InfinitePEPS, env₀::CTMRGEnv; - (finalize!) = OptimKit._finalize!, kwargs..., + operator, peps₀::InfinitePEPS, env₀; (finalize!) = OptimKit._finalize!, kwargs..., ) alg = select_algorithm(fixedpoint, env₀; kwargs...) return fixedpoint(operator, peps₀, env₀, alg; finalize!) end function fixedpoint( - operator, peps₀::InfinitePEPS, env₀::CTMRGEnv, alg::PEPSOptimize; - (finalize!) = OptimKit._finalize!, + operator, peps₀::InfinitePEPS, env₀, alg::PEPSOptimize; (finalize!) = OptimKit._finalize!, ) + # validate inputs + check_input(fixedpoint, peps₀, env₀, alg) + # setup retract and finalize! for symmetrization if isnothing(alg.symmetrization) retract = peps_retract @@ -190,21 +190,9 @@ function fixedpoint( ) end - # :fixed mode compatibility - if !isnothing(alg.gradient_alg) && iterscheme(alg.gradient_alg) == :fixed - if scalartype(env₀) <: Real # incompatible with real environments - env₀ = complex(env₀) - @warn "the provided real environment was converted to a complex environment \ - since :fixed mode generally produces complex gauges; use :diffgauge mode \ - instead by passing gradient_alg=(; iterscheme=:diffgauge) to the fixedpoint \ - keyword arguments to work with purely real environments" - end - end - # initialize info collection vectors T = promote_type(real(scalartype(peps₀)), real(scalartype(env₀))) - truncation_errors = Vector{T}() - condition_numbers = Vector{T}() + contraction_metrics = Vector{NamedTuple}() gradnorms_unitcell = Vector{Matrix{T}}() times = Vector{Float64}() @@ -224,8 +212,7 @@ function fixedpoint( ) ignore_derivatives() do alg.reuse_env && update!(env, env′) - push!(truncation_errors, info.truncation_error) - push!(condition_numbers, info.condition_number) + push!(contraction_metrics, info.contraction_metrics) end return cost_function(ψ, env′, operator) end @@ -240,14 +227,30 @@ function fixedpoint( fg_evaluations = numfg, costs = convergence_history[:, 1], gradnorms = convergence_history[:, 2], - truncation_errors, - condition_numbers, + contraction_metrics, gradnorms_unitcell, times, ) return peps_final, env_final, cost_final, info end +""" + check_input(::typeof(fixedpoint), peps₀, env₀, alg::PEPSOptimize{<:SimultaneousCTMRG}) + +Check compatibility of an initial PEPS and environment with a specified PEPS optimization algorithm. +""" +function check_input(::typeof(fixedpoint), peps₀, env₀, alg::PEPSOptimize) end +function check_input(::typeof(fixedpoint), peps₀, env₀, alg::PEPSOptimize{<:SimultaneousCTMRG, <:GradMode{:fixed}}) + if scalartype(env₀) <: Real # :fixed mode gauge fixing is incompatible with real environments + msg = "the provided real environment is incompatible with :fixed mode \ + since :fixed mode generally produces complex gauges; use :diffgauge mode \ + instead by passing gradient_alg=(; iterscheme=:diffgauge) to the fixedpoint \ + keyword arguments to work with purely real environments and asymmetric CTMRG" + throw(ArgumentError(msg)) + end + return nothing +end + """ peps_normalize(A::InfinitePEPS) diff --git a/src/algorithms/select_algorithm.jl b/src/algorithms/select_algorithm.jl index 8ba6beda1..84dca5b24 100644 --- a/src/algorithms/select_algorithm.jl +++ b/src/algorithms/select_algorithm.jl @@ -32,6 +32,18 @@ function select_algorithm( boundary_alg = select_algorithm(leading_boundary, env₀; boundary_kwargs...) end + # C4vCTMRG-specific defaults + if boundary_alg isa C4vCTMRG + # use :linsolver GradMode since :eigsolver tends to have hiccups + if gradient_alg isa NamedTuple + haskey(gradient_alg, :alg) || (gradient_alg = merge((; alg = :linsolver), gradient_alg)) + end + # symmetrize state and gradient + if isnothing(symmetrization) + symmetrization = RotateReflect() + end + end + # adjust gradient verbosity if gradient_alg isa NamedTuple # TODO: check this: @@ -45,10 +57,6 @@ function select_algorithm( optimizer_alg = merge(defaults, optimizer_alg) end - # symmetrize state and gradient when doing C4v optimization - if boundary_alg isa C4vCTMRG && isnothing(symmetrization) - symmetrization = RotateReflect() - end return PEPSOptimize(; boundary_alg, gradient_alg, optimizer_alg, symmetrization, kwargs...) end diff --git a/test/examples/heisenberg.jl b/test/examples/heisenberg.jl index dc5836537..6abb4146b 100644 --- a/test/examples/heisenberg.jl +++ b/test/examples/heisenberg.jl @@ -50,21 +50,23 @@ end @test all(@. ξ_h > 0 && ξ_v > 0) end -@testset "C4v AD optimization" begin +@testset "C4v AD optimization with scalartype T=$T and projector_alg=$projector_alg" for (T, projector_alg) in + Iterators.product([Float64, ComplexF64], [:c4v_eigh, :c4v_qr]) # initialize symmetric states - Random.seed!(123) + Random.seed!(12345) symm = RotateReflect() - H = heisenberg_XYZ_c4v(InfiniteSquare()) - peps₀ = InfinitePEPS(ComplexSpace(2), ComplexSpace(Dbond)) + H′ = heisenberg_XYZ_c4v(InfiniteSquare()) + H = T <: Real ? real(H′) : H′ + peps₀ = InfinitePEPS(randn, T, ComplexSpace(2), ComplexSpace(Dbond)) peps₀ = peps_normalize(symmetrize!(peps₀, symm)) e₀ = initialize_random_c4v_env(peps₀, ComplexSpace(χenv)) - env₀, = leading_boundary(e₀, peps₀; alg = :c4v) + env₀, = leading_boundary(e₀, peps₀; alg = :c4v, projector_alg) # optimize energy and compute correlation lengths peps, env, E, = fixedpoint( H, peps₀, env₀; optimizer_alg = (; tol = gradtol, maxiter = 25), - boundary_alg = (; alg = :c4v), + boundary_alg = (; alg = :c4v, projector_alg, maxiter = 500), ) ξ_h, ξ_v, = correlation_length(peps, env) @@ -126,11 +128,12 @@ end # benchmark data from Phys. Rev. B 94, 035133 (2016) @test isapprox(e_site, -0.6594; atol = 1.0e-3) + # test if :fixed mode on real tensors errors + @test_throws ArgumentError fixedpoint(ham, peps, env) + # continue with auto differentiation peps_final, env_final, E_final, = fixedpoint( - ham, - peps, - env; + ham, peps, complex(env); # make environment complex explicitly optimizer_alg = (; tol = gradtol, maxiter = 25), boundary_alg = (; maxiter = ctmrg_maxiter), gradient_alg = (; alg = :linsolver, solver_alg = (; alg = :gmres)),