From e86dbde9e09ae94f400cc91bf2a78c1009be277b Mon Sep 17 00:00:00 2001 From: Moritz Lange Date: Fri, 15 Dec 2017 14:49:16 +0100 Subject: [PATCH 1/6] Added mpo_to_pmps() --- mpnum/mpsmpo.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/mpnum/mpsmpo.py b/mpnum/mpsmpo.py index 337935d..9ccf5d2 100644 --- a/mpnum/mpsmpo.py +++ b/mpnum/mpsmpo.py @@ -132,9 +132,10 @@ from . import mparray as mp from .utils import local_to_global, matdot +from scipy.linalg import eigh __all__ = ['mps_to_mpo', 'mps_to_pmps', 'pmps_dm_to_array', - 'pmps_reduction', 'pmps_to_mpo', 'pmps_to_mps', + 'pmps_reduction', 'mpo_to_pmps', 'pmps_to_mpo', 'pmps_to_mps', 'reductions_mpo', 'reductions_mps_as_mpo', 'reductions_mps_as_pmps', 'reductions_pmps', 'reductions'] @@ -372,6 +373,20 @@ def pmps_to_mpo(pmps): return mp.dot(pmps, pmps.adj()) +def mpo_to_pmps(mpo): + """Convert a tensor product MPO into a local purification MPS mixed state. + + :param MPArray mpo: An MPA with two physical legs and rank one on all sites + :returns: An MPA with two physical legs (system and ancilla) + + """ + assert_array_equal(mpo.ranks, 1) + eigs = (eigh(lten[0, ..., 0]) for lten in mpo.lt) + ltens = (i[1] * np.sqrt(i[0])[None, ...] for i in eigs) + pmps = mp.MPArray.from_kron(ltens) + return pmps / mp.norm(pmps) + + def mps_to_pmps(mps): """Convert a pure MPS into a local purification MPS mixed state. From d5c234220847e9a6aa67466c3b9c30def482f8a8 Mon Sep 17 00:00:00 2001 From: Moritz Lange Date: Fri, 15 Dec 2017 16:54:35 +0100 Subject: [PATCH 2/6] Improved the code according to the discussion on the last commit. --- mpnum/mpsmpo.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/mpnum/mpsmpo.py b/mpnum/mpsmpo.py index 9ccf5d2..8bb724f 100644 --- a/mpnum/mpsmpo.py +++ b/mpnum/mpsmpo.py @@ -125,7 +125,6 @@ from __future__ import absolute_import, division, print_function import numpy as np -from numpy.testing import assert_array_equal from six.moves import range @@ -244,7 +243,7 @@ def reductions_mpo(mpa, width=None, startsites=None, stopsites=None): startsites, stopsites = \ _check_reductions_args(len(mpa), width, startsites, stopsites) - assert_array_equal(mpa.ndims, 2) + if not (np.array(mpa.ndims) == 2).all(): raise ValueError('Every site needs to have exactly two physical legs') rem_left = {0: np.array(1, ndmin=2)} rem_right = rem_left.copy() @@ -376,13 +375,13 @@ def pmps_to_mpo(pmps): def mpo_to_pmps(mpo): """Convert a tensor product MPO into a local purification MPS mixed state. - :param MPArray mpo: An MPA with two physical legs and rank one on all sites - :returns: An MPA with two physical legs (system and ancilla) + :param MPArray mpo: An MPA with two physical legs and rank one on all sites + :returns: An MPA with two physical legs (system and ancilla) """ - assert_array_equal(mpo.ranks, 1) - eigs = (eigh(lten[0, ..., 0]) for lten in mpo.lt) - ltens = (i[1] * np.sqrt(i[0])[None, ...] for i in eigs) + if not (np.array(mpo.ranks) == 1).all(): raise ValueError('Only implemented for rank-1 MPOs') + eigs = (eigh(lten[0, ..., 0] / np.trace(lten[0, ..., 0])) for lten in mpo.lt) + ltens = (np.sqrt(vals)[None, ...] * vecs for vals, vecs in eigs) pmps = mp.MPArray.from_kron(ltens) return pmps / mp.norm(pmps) @@ -397,7 +396,7 @@ def mps_to_pmps(mps): :returns: An MPA with two physical legs (system and ancilla) """ - assert_array_equal(mps.ndims, 1) + if not (np.array(mps.ndims) == 1).all(): raise ValueError('Only implemented for MPS') ltens = (lten.reshape(lten.shape[0:2] + (1, lten.shape[2])) for lten in mps.lt) return mp.MPArray(ltens) From c78ece8bed4af02066aae3f8899e18517fd91252 Mon Sep 17 00:00:00 2001 From: Moritz Lange Date: Fri, 15 Dec 2017 17:19:53 +0100 Subject: [PATCH 3/6] Improved the code according to the discussion on the last commit. --- mpnum/mpsmpo.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mpnum/mpsmpo.py b/mpnum/mpsmpo.py index 8bb724f..f6b1fcd 100644 --- a/mpnum/mpsmpo.py +++ b/mpnum/mpsmpo.py @@ -243,7 +243,8 @@ def reductions_mpo(mpa, width=None, startsites=None, stopsites=None): startsites, stopsites = \ _check_reductions_args(len(mpa), width, startsites, stopsites) - if not (np.array(mpa.ndims) == 2).all(): raise ValueError('Every site needs to have exactly two physical legs') + if not (np.array(mpa.ndims) == 2).all(): + raise ValueError('Every site needs to have exactly two physical legs') rem_left = {0: np.array(1, ndmin=2)} rem_right = rem_left.copy() @@ -396,7 +397,8 @@ def mps_to_pmps(mps): :returns: An MPA with two physical legs (system and ancilla) """ - if not (np.array(mps.ndims) == 1).all(): raise ValueError('Only implemented for MPS') + if not (np.array(mps.ndims) == 1).all(): + raise ValueError('Only implemented for unit auxiliary dimensions') ltens = (lten.reshape(lten.shape[0:2] + (1, lten.shape[2])) for lten in mps.lt) return mp.MPArray(ltens) From 4e13652ea8670668b0c984d9ee19a2f6016bb367 Mon Sep 17 00:00:00 2001 From: Moritz Lange Date: Wed, 9 May 2018 14:12:42 +0200 Subject: [PATCH 4/6] Added a first version of a test for mpsmpo.mpo_to_pmps() --- mpnum/mpsmpo.py | 3 ++- tests/mpsmpo_test.py | 13 +++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/mpnum/mpsmpo.py b/mpnum/mpsmpo.py index f6b1fcd..8652229 100644 --- a/mpnum/mpsmpo.py +++ b/mpnum/mpsmpo.py @@ -380,7 +380,8 @@ def mpo_to_pmps(mpo): :returns: An MPA with two physical legs (system and ancilla) """ - if not (np.array(mpo.ranks) == 1).all(): raise ValueError('Only implemented for rank-1 MPOs') + if not (np.array(mpo.ranks) == 1).all(): + raise ValueError('Only implemented for rank-1 MPOs') eigs = (eigh(lten[0, ..., 0] / np.trace(lten[0, ..., 0])) for lten in mpo.lt) ltens = (np.sqrt(vals)[None, ...] * vecs for vals, vecs in eigs) pmps = mp.MPArray.from_kron(ltens) diff --git a/tests/mpsmpo_test.py b/tests/mpsmpo_test.py index 0e50b55..e9a042c 100644 --- a/tests/mpsmpo_test.py +++ b/tests/mpsmpo_test.py @@ -5,6 +5,7 @@ import numpy as np import pytest as pt from numpy.testing import assert_array_almost_equal +from numpy.testing import assert_almost_equal import mpnum.factory as factory import mpnum.mparray as mp @@ -223,6 +224,18 @@ def test_pmps_to_mpo(nr_sites, local_dim, rank, rgen): assert_array_almost_equal(rho_mp, rho_np) +@pt.mark.parametrize('nr_sites, local_dim', pt.MP_TEST_PARAMETERS) +def test_mpo_to_pmps(nr_sites, local_dim, rgen): + pmps = factory.random_mpa(nr_sites, (local_dim, local_dim), 1, + dtype=np.complex_, randstate=rgen) + assert_almost_equal(mp.normdist(mm.mpo_to_pmps(mm.pmps_to_mpo(pmps)), + pmps), 0) + mpo = factory.random_mpa(nr_sites, (local_dim, local_dim), 1, + dtype=np.complex_, randstate=rgen, normalized=True) + assert_almost_equal(mp.normdist(mm.pmps_to_mpo(mm.mpo_to_pmps(mpo)), + mpo), 0) + + @pt.mark.parametrize('nr_sites, local_dim, rank', pt.MP_TEST_PARAMETERS) def test_mps_to_mpo(nr_sites, local_dim, rank, rgen): mps = factory.random_mps(nr_sites, local_dim, rank, randstate=rgen) From 751b201662f914d97a65f8bfdc83629ba08b5fb6 Mon Sep 17 00:00:00 2001 From: Moritz Lange Date: Wed, 9 May 2018 14:43:09 +0200 Subject: [PATCH 5/6] Changed the decorator because there is no parameter rank in test_mpo_to_pmps() --- tests/mpsmpo_test.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/mpsmpo_test.py b/tests/mpsmpo_test.py index e9a042c..53b8858 100644 --- a/tests/mpsmpo_test.py +++ b/tests/mpsmpo_test.py @@ -224,7 +224,8 @@ def test_pmps_to_mpo(nr_sites, local_dim, rank, rgen): assert_array_almost_equal(rho_mp, rho_np) -@pt.mark.parametrize('nr_sites, local_dim', pt.MP_TEST_PARAMETERS) +@pt.mark.parametrize('nr_sites, local_dim', [(1, 7), (2, 3), (3, 2), (6, 2), + (4, 3), (5, 2)]) def test_mpo_to_pmps(nr_sites, local_dim, rgen): pmps = factory.random_mpa(nr_sites, (local_dim, local_dim), 1, dtype=np.complex_, randstate=rgen) From fbd05e5fcc5b480e803c75b5b66fe1549c3345a8 Mon Sep 17 00:00:00 2001 From: Moritz Lange <32869425+MoritzLange@users.noreply.github.com> Date: Tue, 15 Sep 2020 14:45:48 +0200 Subject: [PATCH 6/6] Updated readme to refer to this fork --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e846b3d..2efabe9 100644 --- a/README.md +++ b/README.md @@ -27,9 +27,9 @@ To install the latest stable version run pip install mpnum -If you want to install `mpnum` from source, please run (on Unix) +If you want to install this fork of `mpnum` from source, please run (on Unix) - git clone https://github.com/dseuss/mpnum.git + git clone https://github.com/moritzlange/mpnum.git cd mpnum pip install .