Example #1
0
    def get_tensors(self) -> List[ndarray]:
        """Return the computed tensors. """
        assert self._step >= self._num_steps

        tensors = []

        order = [self._mps.bond_edges[0], self._mps.array_edges[0][0]]
        first_t = self._mps.nodes[0].reorder_edges(order).get_tensor()
        first_t = add_singleton(first_t, 0)
        tensors.append(first_t * self._dimension)

        for i in range(1, len(self._mps.nodes) - 1):
            order = [
                self._mps.bond_edges[i - 1], self._mps.bond_edges[i],
                self._mps.array_edges[i][0]
            ]
            temp_t = self._mps.nodes[i].reorder_edges(order).get_tensor()
            tensors.append(temp_t * self._dimension)

        order = [self._mps.bond_edges[-1], self._mps.array_edges[-1][0]]
        last_t = self._mps.nodes[-1].reorder_edges(order).get_tensor()
        last_t = add_singleton(last_t, 1)
        tensors.append(last_t * self._dimension)

        # apply basis change / transformation
        if not np.allclose(self._unitary_transform,
                           np.identity(self._unitary_transform.shape[0])):
            for i, tensor in enumerate(tensors):
                tmp = create_delta(tensor, [0, 1, 2, 2])
                tmp = np.dot(np.moveaxis(tmp, -2, -1), self._super_u_dagg)
                tmp = np.moveaxis(tmp, -1, -2)
                tmp = np.dot(tmp, self._super_u.T)
                tensors[i] = tmp

        return tensors
    def __init__(
            self,
            tensors: List[np.ndarray],
            initial_tensor: np.ndarray,
            trace: np.ndarray,
            config: Dict):
        """Create a TensorNetworkProcessTensorBackend object. """
        if "backend" in config:
            self._backend = config["backend"]
        else:
            self._backend = None

        if len(tensors) > 0 and len(tensors[0].shape) == 3:
            _tensors = [ create_delta(t, [0, 1, 2, 2]) for t in tensors ]
        elif len(tensors) > 0 and len(tensors[0].shape) == 4:
            _tensors = tensors
        else:
            _tensors = []

        self._tensors = [ tn.Node(t, backend=self._backend) for t in _tensors ]

        if initial_tensor is not None:
            self._initial_tensor = tn.Node(initial_tensor,
                                           backend=self._backend)
        else:
            self._initial_tensor = None

        self._trace = tn.Node(trace, backend=self._backend)

        self._caps = None
Example #3
0
    def initialize(self) -> Tuple[int, ndarray]:
        """See BaseBackend.initialize() for docstring."""
        self._initial_state = copy(self._initial_state).reshape(-1)

        self._super_u = util.left_right_super(
            self._unitary_transform,
            self._unitary_transform.conjugate().T)
        self._super_u_dagg = util.left_right_super(
            self._unitary_transform.conjugate().T, self._unitary_transform)

        self._sum_north_na = na.NodeArray([self._sum_north],
                                          left=False,
                                          right=False,
                                          name="Sum north")

        influences = []
        if self._dkmax is None:
            dkmax_pre_compute = 1
        else:
            dkmax_pre_compute = self._dkmax

        for i in range(dkmax_pre_compute):
            infl = self._influence(i)
            infl_four_legs = create_delta(infl, [1, 0, 0, 1])
            if i == 0:
                tmp = dot(moveaxis(infl_four_legs, 1, -1), self._super_u_dagg)
                tmp = moveaxis(tmp, -1, 1)
                tmp = dot(tmp, self._super_u.T)
                infl_four_legs = tmp
            influences.append(infl_four_legs)

        self._mps = na.NodeArray([self._initial_state],
                                 left=False,
                                 right=False,
                                 name="Thee MPS")
        self._mpo = na.NodeArray(list(reversed(influences)),
                                 left=True,
                                 right=True,
                                 name="Thee Time Evolving MPO")

        self._step = 0
        self._state = self._initial_state

        return self._step, copy(self._state)
Example #4
0
    def initialize(self) -> None:
        """Initializes the PT-TEMPO tensor network. """
        # create mpo
        # create mpo last
        # copy and contrac mpo to mps
        scale = self._dimension

        self._super_u = util.left_right_super(
            self._unitary_transform,
            self._unitary_transform.conjugate().T)
        self._super_u_dagg = util.left_right_super(
            self._unitary_transform.conjugate().T, self._unitary_transform)

        self._sum_north_scaled = self._sum_north * scale

        influences_mpo = []
        influences_mps = []
        for i in range(self._num_infl):
            infl = self._influence(i)
            if i == 0:
                infl = infl / scale
                infl_mpo = create_delta(infl, [1, 1, 0])
                infl_mps = infl.T / scale
            elif i == self._num_infl - 1:
                infl_mpo = add_singleton(infl, 1)
                infl_mpo = add_singleton(infl_mpo, 3)
                infl_mps = add_singleton(infl, 2)
            else:
                infl_mpo = create_delta(infl, [0, 1, 1, 0])
                infl_mps = create_delta(infl / scale, [0, 1, 0])

            influences_mpo.append(infl_mpo)
            influences_mps.append(infl_mps)

        self._mpo = na.NodeArray(influences_mpo,
                                 left=False,
                                 right=True,
                                 name="Thee Time Evolving MPO",
                                 backend=self._backend)

        self._mps = na.NodeArray(influences_mps,
                                 left=False,
                                 right=True,
                                 name="Thee MPS",
                                 backend=self._backend)

        self._mps.svd_sweep(from_index=-1,
                            to_index=0,
                            max_singular_values=None,
                            max_truncation_err=self._epsrel,
                            relative=True)

        self._mps.svd_sweep(from_index=0,
                            to_index=-1,
                            max_singular_values=None,
                            max_truncation_err=self._epsrel,
                            relative=True)

        one = np.array([[1.0]], dtype=NpDtype)
        self._one_na = na.NodeArray([one],
                                    left=True,
                                    right=False,
                                    name="The id",
                                    backend=self._backend)

        self._step = 1
Example #5
0
    def compute_step(self) -> Tuple[int, ndarray]:
        """
        See BaseTempoBackend.compute_step() for docstring.

        For example, for at step 4, we start with:

            A ... self._mps
            B ... self._mpo
            w ... self._sum_west
            n ... self._sum_north_array
            p1 ... prop_1
            p2 ... prop_2

              n  n  n  n
              |  |  |  |

              |  |  |  |     |
        w~~ ~~B~~B~~B~~B~~ ~~p2
              |  |  |  |
                       p1
              |  |  |  |
              A~~A~~A~~A

        return:
            step = 4
            state = contraction of A,B,w,n,p1

        effects:
            self._mpo will grow to the left with the next influence functional
            self._mps will be contraction of A,B,w,p1,p2

        """
        self._step += 1
        prop_1, prop_2 = self._propagators(self._step - 1)
        prop_1_na = na.NodeArray([prop_1],
                                 left=False,
                                 right=False,
                                 name="first half-step")
        prop_2_na = na.NodeArray([prop_2],
                                 left=True,
                                 right=False,
                                 name="second half-step")

        if self._dkmax is None:
            mpo = self._mpo.copy()
            infl = self._influence(len(mpo))
            infl_four_legs = create_delta(infl, [1, 0, 0, 1])
            infl_na = na.NodeArray([infl_four_legs], left=True, right=True)
            self._mpo = na.join(infl_na,
                                self._mpo,
                                name="Thee Time Evolving MPO",
                                copy=False)
        elif self._step < self._dkmax:
            _, mpo = na.split(self._mpo, int(0 - self._step), copy=True)
        else:
            mpo = self._mpo.copy()

        mpo.name = "temporary MPO"
        mpo.apply_vector(self._sum_west, left=True)

        self._mps.zip_up(prop_1_na,
                         axes=[(0, 0)],
                         left_index=-1,
                         right_index=-1,
                         direction="left",
                         max_singular_values=None,
                         max_truncation_err=self._epsrel,
                         relative=True,
                         copy=False)

        self._mps.zip_up(mpo,
                         axes=[(0, 0)],
                         left_index=0,
                         right_index=-1,
                         direction="right",
                         max_singular_values=None,
                         max_truncation_err=self._epsrel,
                         relative=True,
                         copy=False)

        if self._dkmax is not None and self._step >= self._dkmax:
            self._mps.contract(self._sum_north_na,
                               axes=[(0, 0)],
                               left_index=0,
                               right_index=0,
                               direction="right",
                               copy=True)

        self._mps.svd_sweep(from_index=-1,
                            to_index=0,
                            max_singular_values=None,
                            max_truncation_err=self._epsrel,
                            relative=True)

        self._mps = na.join(self._mps,
                            prop_2_na,
                            copy=False,
                            name=f"Thee MPS ({self._step})")

        tmp_mps = self._mps.copy()
        for _ in range(len(tmp_mps) - 1):
            tmp_mps.contract(self._sum_north_na,
                             axes=[(0, 0)],
                             left_index=0,
                             right_index=0,
                             direction="right",
                             copy=True)

        assert len(tmp_mps) == 1
        assert not tmp_mps.left
        assert not tmp_mps.right
        assert tmp_mps.rank == 1
        self._state = tmp_mps.nodes[0].get_tensor()

        return copy(self._step), copy(self._state)