コード例 #1
0
    def operations(self, qubits: Sequence[cirq.QubitId]) -> cirq.OP_TREE:
        """Produce the operations of the ansatz circuit."""
        # TODO implement asymmetric ansatzes?

        for i in range(self.iterations):

            suffix = '-{}'.format(i) if self.iterations > 1 else ''

            # Apply one- and two-body interactions with a swap network that
            # reverses the order of the modes
            def one_and_two_body_interaction(p, q, a, b) -> cirq.OP_TREE:
                if 'T{}_{}'.format(p, q) + suffix in self.params:
                    yield XXYYGate(
                        half_turns=self.params['T{}_{}'.format(p, q) +
                                               suffix]).on(a, b)
                if 'W{}_{}'.format(p, q) + suffix in self.params:
                    yield YXXYGate(
                        half_turns=self.params['W{}_{}'.format(p, q) +
                                               suffix]).on(a, b)
                if 'V{}_{}'.format(p, q) + suffix in self.params:
                    yield cirq.Rot11Gate(
                        half_turns=self.params['V{}_{}'.format(p, q) +
                                               suffix]).on(a, b)

            yield swap_network(qubits,
                               one_and_two_body_interaction,
                               fermionic=True)
            qubits = qubits[::-1]

            # Apply one-body potential
            yield (cirq.RotZGate(half_turns=self.params['U{}'.format(p) +
                                                        suffix]).on(qubits[p])
                   for p in range(len(qubits))
                   if 'U{}'.format(p) + suffix in self.params)

            # Apply one- and two-body interactions again. This time, reorder
            # them so that the entire iteration is symmetric
            def one_and_two_body_interaction_reversed_order(p, q, a,
                                                            b) -> cirq.OP_TREE:
                if 'V{}_{}'.format(p, q) + suffix in self.params:
                    yield cirq.Rot11Gate(
                        half_turns=self.params['V{}_{}'.format(p, q) +
                                               suffix]).on(a, b)
                if 'W{}_{}'.format(p, q) + suffix in self.params:
                    yield YXXYGate(
                        half_turns=self.params['W{}_{}'.format(p, q) +
                                               suffix]).on(a, b)
                if 'T{}_{}'.format(p, q) + suffix in self.params:
                    yield XXYYGate(
                        half_turns=self.params['T{}_{}'.format(p, q) +
                                               suffix]).on(a, b)

            yield swap_network(qubits,
                               one_and_two_body_interaction_reversed_order,
                               fermionic=True,
                               offset=True)
            qubits = qubits[::-1]
コード例 #2
0
    def operations(self, qubits):
        param_set = set(self.params())
        for i in range(self.iterations):
            # Apply one- and two-body interactions with a swap network that
            # reverses the order of the modes
            def one_and_two_body_interaction(p, q, a, b) -> cirq.OP_TREE:
                tv_symbol = LetterWithSubscripts('Tv', i)
                t_symbol = LetterWithSubscripts('T', p, q, i)
                w_symbol = LetterWithSubscripts('W', p, q, i)
                v_symbol = LetterWithSubscripts('V', p, q, i)
                if custom_is_vertical_edge(p, q,
                                           self.hubbard.lattice.x_dimension,
                                           self.hubbard.lattice.y_dimension,
                                           self.hubbard.lattice.periodic):
                    yield cirq.ISwapPowGate(exponent=-tv_symbol).on(a, b)
                if t_symbol in param_set:
                    yield cirq.ISwapPowGate(exponent=-t_symbol).on(a, b)
                if w_symbol in param_set:
                    yield cirq.PhasedISwapPowGate(exponent=w_symbol).on(a, b)
                if v_symbol in param_set:
                    yield cirq.CZPowGate(exponent=v_symbol).on(a, b)

            yield swap_network(qubits,
                               one_and_two_body_interaction,
                               fermionic=True)
            qubits = qubits[::-1]

            # Apply one- and two-body interactions again. This time, reorder
            # them so that the entire iteration is symmetric
            def one_and_two_body_interaction_reversed_order(p, q, a,
                                                            b) -> cirq.OP_TREE:
                tv_symbol = LetterWithSubscripts('Tv', i)
                t_symbol = LetterWithSubscripts('T', p, q, i)
                w_symbol = LetterWithSubscripts('W', p, q, i)
                v_symbol = LetterWithSubscripts('V', p, q, i)
                if v_symbol in param_set:
                    yield cirq.CZPowGate(exponent=v_symbol).on(a, b)
                if w_symbol in param_set:
                    yield cirq.PhasedISwapPowGate(exponent=w_symbol).on(a, b)
                if t_symbol in param_set:
                    yield cirq.ISwapPowGate(exponent=-t_symbol).on(a, b)
                if custom_is_vertical_edge(p, q,
                                           self.hubbard.lattice.x_dimension,
                                           self.hubbard.lattice.y_dimension,
                                           self.hubbard.lattice.periodic):
                    yield cirq.ISwapPowGate(exponent=-tv_symbol).on(a, b)

            yield swap_network(qubits,
                               one_and_two_body_interaction_reversed_order,
                               fermionic=True,
                               offset=True)
            qubits = qubits[::-1]
コード例 #3
0
    def trotter_step(
            self,
            qubits: Sequence[cirq.QubitId],
            time: float,
            control_qubit: Optional[cirq.QubitId] = None) -> cirq.OP_TREE:

        n_qubits = len(qubits)

        # Apply one- and two-body interactions for half of the full time
        def one_and_two_body_interaction(p, q, a, b) -> cirq.OP_TREE:
            yield ControlledXXYYGate(duration=0.5 *
                                     self.hamiltonian.one_body[p, q].real *
                                     time).on(control_qubit, a, b)
            yield ControlledYXXYGate(duration=0.5 *
                                     self.hamiltonian.one_body[p, q].imag *
                                     time).on(control_qubit, a, b)
            yield Rot111Gate(rads=-self.hamiltonian.two_body[p, q] * time).on(
                control_qubit, a, b)

        yield swap_network(qubits,
                           one_and_two_body_interaction,
                           fermionic=True)
        qubits = qubits[::-1]

        # Apply one-body potential for the full time
        yield (cirq.Rot11Gate(rads=-self.hamiltonian.one_body[i, i].real *
                              time).on(control_qubit, qubits[i])
               for i in range(n_qubits))

        # Apply one- and two-body interactions for half of the full time
        # This time, reorder the operations so that the entire Trotter step is
        # symmetric
        def one_and_two_body_interaction_reverse_order(p, q, a,
                                                       b) -> cirq.OP_TREE:
            yield Rot111Gate(rads=-self.hamiltonian.two_body[p, q] * time).on(
                control_qubit, a, b)
            yield ControlledYXXYGate(duration=0.5 *
                                     self.hamiltonian.one_body[p, q].imag *
                                     time).on(control_qubit, a, b)
            yield ControlledXXYYGate(duration=0.5 *
                                     self.hamiltonian.one_body[p, q].real *
                                     time).on(control_qubit, a, b)

        yield swap_network(qubits,
                           one_and_two_body_interaction_reverse_order,
                           fermionic=True,
                           offset=True)

        # Apply phase from constant term
        yield cirq.RotZGate(rads=-self.hamiltonian.constant *
                            time).on(control_qubit)
コード例 #4
0
    def operations(self, qubits: Sequence[cirq.Qid]) -> cirq.OP_TREE:
        """Produce the operations of the ansatz circuit."""
        # TODO implement asymmetric ansatz

        param_set = set(self.params())

        for i in range(self.iterations):

            # Apply one- and two-body interactions with a swap network that
            # reverses the order of the modes
            def one_and_two_body_interaction(p, q, a, b) -> cirq.OP_TREE:
                t_symbol = LetterWithSubscripts('T', p, q, i)
                w_symbol = LetterWithSubscripts('W', p, q, i)
                v_symbol = LetterWithSubscripts('V', p, q, i)
                if t_symbol in param_set:
                    yield XXYYPowGate(exponent=t_symbol).on(a, b)
                if w_symbol in param_set:
                    yield YXXYPowGate(exponent=w_symbol).on(a, b)
                if v_symbol in param_set:
                    yield cirq.CZPowGate(exponent=v_symbol).on(a, b)

            yield swap_network(qubits,
                               one_and_two_body_interaction,
                               fermionic=True)
            qubits = qubits[::-1]

            # Apply one-body potential
            for p in range(len(qubits)):
                u_symbol = LetterWithSubscripts('U', p, i)
                if u_symbol in param_set:
                    yield cirq.ZPowGate(exponent=u_symbol).on(qubits[p])

            # Apply one- and two-body interactions again. This time, reorder
            # them so that the entire iteration is symmetric
            def one_and_two_body_interaction_reversed_order(p, q, a,
                                                            b) -> cirq.OP_TREE:
                t_symbol = LetterWithSubscripts('T', p, q, i)
                w_symbol = LetterWithSubscripts('W', p, q, i)
                v_symbol = LetterWithSubscripts('V', p, q, i)
                if v_symbol in param_set:
                    yield cirq.CZPowGate(exponent=v_symbol).on(a, b)
                if w_symbol in param_set:
                    yield YXXYPowGate(exponent=w_symbol).on(a, b)
                if t_symbol in param_set:
                    yield XXYYPowGate(exponent=t_symbol).on(a, b)

            yield swap_network(qubits,
                               one_and_two_body_interaction_reversed_order,
                               fermionic=True,
                               offset=True)
            qubits = qubits[::-1]
コード例 #5
0
ファイル: low_rank.py プロジェクト: idk3/OpenFermion-Cirq
 def finish(self,
            qubits: Sequence[cirq.QubitId],
            n_steps: int,
            control_qubit: Optional[cirq.QubitId] = None,
            omit_final_swaps: bool = False) -> cirq.OP_TREE:
     if not omit_final_swaps:
         # If the number of fermionic swap networks was odd,
         # swap the modes back
         if n_steps & 1:
             yield swap_network(qubits, fermionic=True)
             # If the total number of swap networks was odd,
             # swap the qubits back
             if len(self.eigenvalues) & 1:
                 yield swap_network(qubits)
コード例 #6
0
    def trotter_step(
            self,
            qubits: Sequence[cirq.QubitId],
            time: float,
            control_qubit: Optional[cirq.QubitId] = None) -> cirq.OP_TREE:

        n_qubits = len(qubits)

        # Apply one- and two-body interactions for the full time
        def one_and_two_body_interaction(p, q, a, b) -> cirq.OP_TREE:
            yield XXYYGate(duration=self.hamiltonian.one_body[p, q].real *
                           time).on(a, b)
            yield YXXYGate(duration=self.hamiltonian.one_body[p, q].imag *
                           time).on(a, b)
            yield cirq.Rot11Gate(rads=-2 * self.hamiltonian.two_body[p, q] *
                                 time).on(a, b)

        yield swap_network(qubits,
                           one_and_two_body_interaction,
                           fermionic=True)
        qubits = qubits[::-1]

        # Apply one-body potential for the full time
        yield (cirq.RotZGate(rads=-self.hamiltonian.one_body[i, i].real *
                             time).on(qubits[i]) for i in range(n_qubits))
コード例 #7
0
    def trotter_step(self,
                     qubits: Sequence[cirq.Qid],
                     time: float,
                     control_qubit: Optional[cirq.Qid] = None) -> cirq.OP_TREE:

        n_qubits = len(qubits)

        if not isinstance(control_qubit, cirq.Qid):
            raise TypeError('Control qudit must be specified.')

        # Simulate the two-body terms for the full time
        def two_body_interaction(p, q, a, b) -> cirq.OP_TREE:
            yield rot111(-2 * self.hamiltonian.two_body[p, q] * time).on(
                cast(cirq.Qid, control_qubit), a, b)

        yield swap_network(qubits, two_body_interaction)
        # The qubit ordering has been reversed
        qubits = qubits[::-1]

        # Rotate to the basis in which the one-body term is diagonal
        yield cirq.inverse(
            bogoliubov_transform(qubits, self.basis_change_matrix))

        # Simulate the one-body terms for the full time
        yield (rot11(rads=-self.orbital_energies[i] * time).on(
            control_qubit, qubits[i]) for i in range(n_qubits))

        # Rotate back to the computational basis
        yield bogoliubov_transform(qubits, self.basis_change_matrix)

        # Apply phase from constant term
        yield cirq.rz(rads=-self.hamiltonian.constant * time).on(control_qubit)
コード例 #8
0
    def trotter_step(self,
                     qubits: Sequence[cirq.Qid],
                     time: float,
                     control_qubit: Optional[cirq.Qid] = None) -> cirq.OP_TREE:

        n_qubits = len(qubits)

        # Apply one- and two-body interactions for the full time
        def one_and_two_body_interaction(p, q, a, b) -> cirq.OP_TREE:
            yield CRxxyy(self.hamiltonian.one_body[p, q].real * time).on(
                control_qubit, a, b)
            yield CRyxxy(self.hamiltonian.one_body[p, q].imag * time).on(
                control_qubit, a, b)
            yield rot111(-2 * self.hamiltonian.two_body[p, q] * time).on(
                control_qubit, a, b)

        yield swap_network(qubits,
                           one_and_two_body_interaction,
                           fermionic=True)
        qubits = qubits[::-1]

        # Apply one-body potential for the full time
        yield (rot11(rads=-self.hamiltonian.one_body[i, i].real * time).on(
            control_qubit, qubits[i]) for i in range(n_qubits))

        # Apply phase from constant term
        yield cirq.rz(rads=-self.hamiltonian.constant * time).on(control_qubit)
コード例 #9
0
    def trotter_step(
            self,
            qubits: Sequence[cirq.QubitId],
            time: float,
            control_qubit: Optional[cirq.QubitId] = None) -> cirq.OP_TREE:

        n_qubits = len(qubits)

        # Simulate the one-body terms for half of the full time
        yield (cirq.Rz(rads=-0.5 * self.orbital_energies[i] * time).on(
            qubits[i]) for i in range(n_qubits))

        # Rotate to the computational basis
        yield bogoliubov_transform(qubits, self.basis_change_matrix)

        # Simulate the two-body terms for the full time
        def two_body_interaction(p, q, a, b) -> cirq.OP_TREE:
            yield rot11(rads=-2 * self.hamiltonian.two_body[p, q] * time).on(
                a, b)

        yield swap_network(qubits, two_body_interaction)
        # The qubit ordering has been reversed
        qubits = qubits[::-1]

        # Rotate back to the basis in which the one-body term is diagonal
        yield cirq.inverse(
            bogoliubov_transform(qubits, self.basis_change_matrix))

        # Simulate the one-body terms for half of the full time
        yield (cirq.Rz(rads=-0.5 * self.orbital_energies[i] * time).on(
            qubits[i]) for i in range(n_qubits))
コード例 #10
0
    def trotter_step(self,
                     qubits: Sequence[cirq.Qid],
                     time: float,
                     control_qubit: Optional[cirq.Qid] = None) -> cirq.OP_TREE:

        n_qubits = len(qubits)

        if not isinstance(control_qubit, cirq.Qid):
            raise TypeError('Control qudit must be specified.')

        # Apply one- and two-body interactions for half of the full time
        def one_and_two_body_interaction(p, q, a, b) -> cirq.OP_TREE:
            yield CRxxyy(0.5 * self.hamiltonian.one_body[p, q].real * time).on(
                cast(cirq.Qid, control_qubit), a, b)
            yield CRyxxy(0.5 * self.hamiltonian.one_body[p, q].imag * time).on(
                cast(cirq.Qid, control_qubit), a, b)
            yield rot111(-self.hamiltonian.two_body[p, q] * time).on(
                cast(cirq.Qid, control_qubit), a, b)

        yield swap_network(qubits,
                           one_and_two_body_interaction,
                           fermionic=True)
        qubits = qubits[::-1]

        # Apply one-body potential for the full time
        yield (rot11(rads=-self.hamiltonian.one_body[i, i].real * time).on(
            control_qubit, qubits[i]) for i in range(n_qubits))

        # Apply one- and two-body interactions for half of the full time
        # This time, reorder the operations so that the entire Trotter step is
        # symmetric
        def one_and_two_body_interaction_reverse_order(p, q, a,
                                                       b) -> cirq.OP_TREE:
            yield rot111(-self.hamiltonian.two_body[p, q] * time).on(
                cast(cirq.Qid, control_qubit), a, b)
            yield CRyxxy(0.5 * self.hamiltonian.one_body[p, q].imag * time).on(
                cast(cirq.Qid, control_qubit), a, b)
            yield CRxxyy(0.5 * self.hamiltonian.one_body[p, q].real * time).on(
                cast(cirq.Qid, control_qubit), a, b)

        yield swap_network(qubits,
                           one_and_two_body_interaction_reverse_order,
                           fermionic=True,
                           offset=True)

        # Apply phase from constant term
        yield cirq.rz(rads=-self.hamiltonian.constant * time).on(control_qubit)
コード例 #11
0
ファイル: low_rank.py プロジェクト: viathor/OpenFermion-Cirq
    def trotter_step(
            self,
            qubits: Sequence[cirq.Qid],
            time: float,
            control_qubit: Optional[cirq.Qid]=None
            ) -> cirq.OP_TREE:

        if not isinstance(control_qubit, cirq.Qid):
            raise NotImplementedError('Control qudit must be specified.')
        n_qubits = len(qubits)

        # Change to the basis in which the one-body term is diagonal
        yield bogoliubov_transform(
                qubits, self.one_body_basis_change_matrix.T.conj())

        # Simulate the one-body terms.
        for p in range(n_qubits):
            yield rot11(rads=
                    -self.one_body_energies[p] * time
                    ).on(control_qubit, qubits[p])

        # Simulate each singular vector of the two-body terms.
        prior_basis_matrix = self.one_body_basis_change_matrix

        for j in range(len(self.eigenvalues)):

            # Get the two-body coefficients and basis change matrix.
            two_body_coefficients = self.scaled_density_density_matrices[j]
            basis_change_matrix = self.basis_change_matrices[j]

            # Merge previous basis change matrix with the inverse of the
            # current one
            merged_basis_change_matrix = numpy.dot(prior_basis_matrix,
                                                   basis_change_matrix.T.conj())
            yield bogoliubov_transform(qubits, merged_basis_change_matrix)

            # Simulate the off-diagonal two-body terms.
            yield swap_network(
                    qubits,
                    lambda p, q, a, b: rot111(
                        -2 * two_body_coefficients[p, q] * time).on(
                            control_qubit, a, b))
            qubits = qubits[::-1]

            # Simulate the diagonal two-body terms.
            yield (rot11(rads=
                       -two_body_coefficients[k, k] * time).on(
                           control_qubit, qubits[k])
                   for k in range(n_qubits))

            # Update prior basis change matrix.
            prior_basis_matrix = basis_change_matrix

        # Undo final basis transformation.
        yield bogoliubov_transform(qubits, prior_basis_matrix)

        # Apply phase from constant term
        yield cirq.rz(rads=
                -self.hamiltonian.constant * time).on(control_qubit)
コード例 #12
0
    def operations(self, qubits: Sequence[cirq.Qid]) -> cirq.OP_TREE:
        """Produce the operations of the ansatz circuit."""

        for i in range(self.iterations):

            # Apply one- and two-body interactions with a swap network that
            # reverses the order of the modes
            def one_and_two_body_interaction(p, q, a, b) -> cirq.OP_TREE:
                th_symbol = LetterWithSubscripts('Th', i)
                tv_symbol = LetterWithSubscripts('Tv', i)
                v_symbol = LetterWithSubscripts('V', i)
                if _is_horizontal_edge(p, q, self.x_dim, self.y_dim,
                                       self.periodic):
                    yield cirq.ISwapPowGate(exponent=-th_symbol).on(a, b)
                if _is_vertical_edge(p, q, self.x_dim, self.y_dim,
                                     self.periodic):
                    yield cirq.ISwapPowGate(exponent=-tv_symbol).on(a, b)
                if _are_same_site_opposite_spin(p, q, self.x_dim * self.y_dim):
                    yield cirq.CZPowGate(exponent=v_symbol).on(a, b)

            yield swap_network(qubits,
                               one_and_two_body_interaction,
                               fermionic=True)
            qubits = qubits[::-1]

            # Apply one- and two-body interactions again. This time, reorder
            # them so that the entire iteration is symmetric
            def one_and_two_body_interaction_reversed_order(p, q, a,
                                                            b) -> cirq.OP_TREE:
                th_symbol = LetterWithSubscripts('Th', i)
                tv_symbol = LetterWithSubscripts('Tv', i)
                v_symbol = LetterWithSubscripts('V', i)
                if _are_same_site_opposite_spin(p, q, self.x_dim * self.y_dim):
                    yield cirq.CZPowGate(exponent=v_symbol).on(a, b)
                if _is_vertical_edge(p, q, self.x_dim, self.y_dim,
                                     self.periodic):
                    yield cirq.ISwapPowGate(exponent=-tv_symbol).on(a, b)
                if _is_horizontal_edge(p, q, self.x_dim, self.y_dim,
                                       self.periodic):
                    yield cirq.ISwapPowGate(exponent=-th_symbol).on(a, b)

            yield swap_network(qubits,
                               one_and_two_body_interaction_reversed_order,
                               fermionic=True,
                               offset=True)
            qubits = qubits[::-1]
コード例 #13
0
 def finish(self,
            qubits: Sequence[cirq.QubitId],
            n_steps: int,
            control_qubit: Optional[cirq.QubitId] = None,
            omit_final_swaps: bool = False) -> cirq.OP_TREE:
     # If the number of Trotter steps is odd, possibly swap qubits back
     if n_steps & 1 and not omit_final_swaps:
         yield swap_network(qubits)
コード例 #14
0
 def finish(self,
            qubits: Sequence[cirq.Qid],
            n_steps: int,
            control_qubit: Optional[cirq.Qid] = None,
            omit_final_swaps: bool = False) -> cirq.OP_TREE:
     if not omit_final_swaps:
         # If the number of swap networks was odd, swap the qubits back
         if n_steps & 1 and len(self.eigenvalues) & 1:
             yield swap_network(qubits)
コード例 #15
0
 def finish(self,
            qubits: Sequence[cirq.QubitId],
            n_steps: int,
            control_qubit: Optional[cirq.QubitId] = None,
            omit_final_swaps: bool = False) -> cirq.OP_TREE:
     # Rotate back to the computational basis
     yield bogoliubov_transform(qubits, self.basis_change_matrix)
     # If the number of Trotter steps is odd, possibly swap qubits back
     if n_steps & 1 and not omit_final_swaps:
         yield swap_network(qubits)
コード例 #16
0
    def operations(self, qubits: Sequence[cirq.Qid]) -> cirq.OP_TREE:
        """Produce the operations of the ansatz circuit."""

        n_qubits = len(qubits)
        param_set = set(self.params())

        for i in range(self.iterations):

            # Change to the basis in which the one-body term is diagonal
            yield bogoliubov_transform(
                    qubits, self.one_body_basis_change_matrix.T.conj())

            # Simulate the one-body terms.
            for p in range(n_qubits):
                u_symbol = LetterWithSubscripts('U', p, i)
                if u_symbol in param_set:
                    yield cirq.ZPowGate(exponent=u_symbol).on(qubits[p])

            # Simulate each singular vector of the two-body terms.
            prior_basis_matrix = self.one_body_basis_change_matrix

            for j in range(len(self.eigenvalues)):

                # Get the basis change matrix.
                basis_change_matrix = self.basis_change_matrices[j]

                # Merge previous basis change matrix with the inverse of the
                # current one
                merged_basis_change_matrix = numpy.dot(
                        prior_basis_matrix,
                        basis_change_matrix.T.conj())
                yield bogoliubov_transform(qubits, merged_basis_change_matrix)

                # Simulate the off-diagonal two-body terms.
                def two_body_interaction(p, q, a, b) -> cirq.OP_TREE:
                    v_symbol = LetterWithSubscripts('V', p, q, j, i)
                    if v_symbol in param_set:
                        yield cirq.CZPowGate(exponent=v_symbol).on(a, b)
                yield swap_network(qubits, two_body_interaction)
                qubits = qubits[::-1]

                # Simulate the diagonal two-body terms.
                for p in range(n_qubits):
                    u_symbol = LetterWithSubscripts('U', p, j, i)
                    if u_symbol in param_set:
                        yield cirq.ZPowGate(exponent=u_symbol).on(qubits[p])

                # Update prior basis change matrix.
                prior_basis_matrix = basis_change_matrix

            # Undo final basis transformation.
            yield bogoliubov_transform(qubits, prior_basis_matrix)
コード例 #17
0
ファイル: low_rank.py プロジェクト: zx616/OpenFermion-Cirq
    def trotter_step(
            self,
            qubits: Sequence[cirq.Qid],
            time: float,
            control_qubit: Optional[cirq.Qid]=None
            ) -> cirq.OP_TREE:

        n_qubits = len(qubits)

        # Change to the basis in which the one-body term is diagonal
        yield bogoliubov_transform(
                qubits, self.one_body_basis_change_matrix.T.conj())

        # Simulate the one-body terms.
        for p in range(n_qubits):
            yield cirq.Rz(rads=
                    -self.one_body_energies[p] * time
                    ).on(qubits[p])

        # Simulate each singular vector of the two-body terms.
        prior_basis_matrix = self.one_body_basis_change_matrix

        for j in range(len(self.eigenvalues)):

            # Get the two-body coefficients and basis change matrix.
            two_body_coefficients = self.scaled_density_density_matrices[j]
            basis_change_matrix = self.basis_change_matrices[j]

            # Merge previous basis change matrix with the inverse of the
            # current one
            merged_basis_change_matrix = numpy.dot(prior_basis_matrix,
                                                   basis_change_matrix.T.conj())
            yield bogoliubov_transform(qubits, merged_basis_change_matrix)

            # Simulate the off-diagonal two-body terms.
            yield swap_network(
                    qubits,
                    lambda p, q, a, b: rot11(rads=
                        -2 * two_body_coefficients[p, q] * time).on(a, b))
            qubits = qubits[::-1]

            # Simulate the diagonal two-body terms.
            for p in range(n_qubits):
                yield cirq.Rz(rads=
                        -two_body_coefficients[p, p] * time
                        ).on(qubits[p])

            # Update prior basis change matrix
            prior_basis_matrix = basis_change_matrix

        # Undo final basis transformation
        yield bogoliubov_transform(qubits, prior_basis_matrix)
コード例 #18
0
    def operations(self, qubits: Sequence[cirq.QubitId]) -> cirq.OP_TREE:
        """Produce the operations of the ansatz circuit."""
        # TODO implement asymmetric ansatz

        # Change to the basis in which the one-body term is diagonal
        yield cirq.inverse(
            bogoliubov_transform(qubits, self.basis_change_matrix))

        for i in range(self.iterations):

            suffix = '-{}'.format(i) if self.iterations > 1 else ''

            # Simulate one-body terms
            yield (cirq.RotZGate(half_turns=self.params['U{}'.format(p) +
                                                        suffix]).on(qubits[p])
                   for p in range(len(qubits))
                   if 'U{}'.format(p) + suffix in self.params)

            # Rotate to the computational basis
            yield bogoliubov_transform(qubits, self.basis_change_matrix)

            # Simulate the two-body terms
            def two_body_interaction(p, q, a, b) -> cirq.OP_TREE:
                if 'V{}_{}'.format(p, q) + suffix in self.params:
                    yield cirq.Rot11Gate(
                        half_turns=self.params['V{}_{}'.format(p, q) +
                                               suffix]).on(a, b)

            yield swap_network(qubits, two_body_interaction)
            qubits = qubits[::-1]

            # Rotate back to the basis in which the one-body term is diagonal
            yield cirq.inverse(
                bogoliubov_transform(qubits, self.basis_change_matrix))

            # Simulate one-body terms again
            yield (cirq.RotZGate(half_turns=self.params['U{}'.format(p) +
                                                        suffix]).on(qubits[p])
                   for p in range(len(qubits))
                   if 'U{}'.format(p) + suffix in self.params)

        # Rotate to the computational basis
        yield bogoliubov_transform(qubits, self.basis_change_matrix)
コード例 #19
0
    def operations(self, qubits: Sequence[cirq.QubitId]) -> cirq.OP_TREE:
        """Produce the operations of the ansatz circuit."""
        # TODO implement asymmetric ansatz

        param_set = set(self.params())

        # Change to the basis in which the one-body term is diagonal
        yield cirq.inverse(
            bogoliubov_transform(qubits, self.basis_change_matrix))

        for i in range(self.iterations):

            # Simulate one-body terms
            for p in range(len(qubits)):
                u_symbol = LetterWithSubscripts('U', p, i)
                if u_symbol in param_set:
                    yield cirq.RotZGate(half_turns=u_symbol).on(qubits[p])

            # Rotate to the computational basis
            yield bogoliubov_transform(qubits, self.basis_change_matrix)

            # Simulate the two-body terms
            def two_body_interaction(p, q, a, b) -> cirq.OP_TREE:
                v_symbol = LetterWithSubscripts('V', p, q, i)
                if v_symbol in param_set:
                    yield cirq.Rot11Gate(half_turns=v_symbol).on(a, b)

            yield swap_network(qubits, two_body_interaction)
            qubits = qubits[::-1]

            # Rotate back to the basis in which the one-body term is diagonal
            yield cirq.inverse(
                bogoliubov_transform(qubits, self.basis_change_matrix))

            # Simulate one-body terms again
            for p in range(len(qubits)):
                u_symbol = LetterWithSubscripts('U', p, i)
                if u_symbol in param_set:
                    yield cirq.RotZGate(half_turns=u_symbol).on(qubits[p])

        # Rotate to the computational basis
        yield bogoliubov_transform(qubits, self.basis_change_matrix)
コード例 #20
0
def test_swap_network():
    n_qubits = 4
    qubits = cirq.LineQubit.range(n_qubits)

    circuit = cirq.Circuit.from_ops(
            swap_network(qubits, lambda i, j, q0, q1: XXYY(q0, q1)),
            strategy=cirq.InsertStrategy.EARLIEST)
    cirq.testing.assert_has_diagram(circuit, """
0: ───XXYY───×──────────────XXYY───×──────────────
      │      │              │      │
1: ───XXYY───×───XXYY───×───XXYY───×───XXYY───×───
                 │      │              │      │
2: ───XXYY───×───XXYY───×───XXYY───×───XXYY───×───
      │      │              │      │
3: ───XXYY───×──────────────XXYY───×──────────────
""")

    circuit = cirq.Circuit.from_ops(
            swap_network(qubits, lambda i, j, q0, q1: XXYY(q0, q1),
                         fermionic=True, offset=True),
            strategy=cirq.InsertStrategy.EARLIEST)
    cirq.testing.assert_has_diagram(circuit, """
0    1    2    3
│    │    │    │
│    XXYY─XXYY │
│    │    │    │
│    ×ᶠ───×ᶠ   │
│    │    │    │
XXYY─XXYY XXYY─XXYY
│    │    │    │
×ᶠ───×ᶠ   ×ᶠ───×ᶠ
│    │    │    │
│    XXYY─XXYY │
│    │    │    │
│    ×ᶠ───×ᶠ   │
│    │    │    │
XXYY─XXYY XXYY─XXYY
│    │    │    │
×ᶠ───×ᶠ   ×ᶠ───×ᶠ
│    │    │    │
""", transpose=True)

    n_qubits = 5
    qubits = cirq.LineQubit.range(n_qubits)

    circuit = cirq.Circuit.from_ops(
            swap_network(qubits, lambda i, j, q0, q1: (),
                         fermionic=True),
            strategy=cirq.InsertStrategy.EARLIEST)
    cirq.testing.assert_has_diagram(circuit, """
0: ───×ᶠ────────×ᶠ────────×ᶠ───
      │         │         │
1: ───×ᶠ───×ᶠ───×ᶠ───×ᶠ───×ᶠ───
           │         │
2: ───×ᶠ───×ᶠ───×ᶠ───×ᶠ───×ᶠ───
      │         │         │
3: ───×ᶠ───×ᶠ───×ᶠ───×ᶠ───×ᶠ───
           │         │
4: ────────×ᶠ────────×ᶠ────────
""")

    circuit = cirq.Circuit.from_ops(
            swap_network(qubits, lambda i, j, q0, q1: (),
                         offset=True),
            strategy=cirq.InsertStrategy.EARLIEST)
    cirq.testing.assert_has_diagram(circuit, """
0 1 2 3 4
│ │ │ │ │
│ ×─× ×─×
│ │ │ │ │
×─× ×─× │
│ │ │ │ │
│ ×─× ×─×
│ │ │ │ │
×─× ×─× │
│ │ │ │ │
│ ×─× ×─×
│ │ │ │ │
""", transpose=True)
コード例 #21
0
    def trotter_step(
            self,
            qubits: Sequence[cirq.QubitId],
            time: float,
            control_qubit: Optional[cirq.QubitId]=None
            ) -> cirq.OP_TREE:

        n_qubits = len(qubits)

        # Simulate the off-diagonal one-body terms.
        yield swap_network(
                qubits,
                lambda p, q, a, b: ControlledXXYYGate(duration=
                    self.one_body_coefficients[p, q].real * time).on(
                        control_qubit, a, b),
                fermionic=True)
        qubits = qubits[::-1]

        # Simulate the diagonal one-body terms.
        yield (cirq.Rot11Gate(rads=
                   -self.one_body_coefficients[j, j].real * time).on(
                       control_qubit, qubits[j])
               for j in range(n_qubits))

        # Simulate each singular vector of the two-body terms.
        prior_basis_matrix = numpy.identity(n_qubits, complex)
        for j in range(len(self.eigenvalues)):

            # Get the basis change matrix and its inverse.
            two_body_coefficients = self.scaled_density_density_matrices[j]
            basis_change_matrix = self.basis_change_matrices[j]

            # If the basis change matrix is unitary, merge rotations.
            # Otherwise, you must simulate two basis rotations.
            is_unitary = cirq.is_unitary(basis_change_matrix)
            if is_unitary:
                inverse_basis_matrix = numpy.conjugate(
                    numpy.transpose(basis_change_matrix))
                merged_basis_matrix = numpy.dot(prior_basis_matrix,
                                                inverse_basis_matrix)
                yield bogoliubov_transform(qubits, merged_basis_matrix)
            else:
                # TODO add LiH test to cover this.
                # coverage: ignore
                if j:
                    yield bogoliubov_transform(qubits, prior_basis_matrix)
                yield cirq.inverse(
                    bogoliubov_transform(qubits, basis_change_matrix))

            # Simulate the off-diagonal two-body terms.
            yield swap_network(
                    qubits,
                    lambda p, q, a, b: Rot111Gate(rads=
                        -2 * two_body_coefficients[p, q] * time).on(
                            control_qubit, a, b))
            qubits = qubits[::-1]

            # Simulate the diagonal two-body terms.
            yield (cirq.Rot11Gate(rads=
                       -two_body_coefficients[k, k] * time).on(
                           control_qubit, qubits[k])
                   for k in range(n_qubits))

            # Undo basis transformation non-unitary case.
            # Else, set basis change matrix to prior matrix for merging.
            if is_unitary:
                prior_basis_matrix = basis_change_matrix
            else:
                # TODO add LiH test to cover this.
                # coverage: ignore
                yield bogoliubov_transform(qubits, basis_change_matrix)
                prior_basis_matrix = numpy.identity(n_qubits, complex)

        # Undo final basis transformation in unitary case.
        if is_unitary:
            yield bogoliubov_transform(qubits, prior_basis_matrix)

        # Apply phase from constant term
        yield cirq.RotZGate(rads=-self.constant * time).on(control_qubit)
コード例 #22
0
def test_swap_network():
    n_qubits = 4
    qubits = cirq.LineQubit.range(n_qubits)

    circuit = cirq.Circuit.from_ops(swap_network(
        qubits, lambda i, j, q0, q1: XXYY(q0, q1)),
                                    strategy=cirq.InsertStrategy.EARLIEST)
    assert circuit.to_text_diagram(transpose=False).strip() == """
0: ───XXYY───×──────────────XXYY───×──────────────
      │      │              │      │
1: ───XXYY───×───XXYY───×───XXYY───×───XXYY───×───
                 │      │              │      │
2: ───XXYY───×───XXYY───×───XXYY───×───XXYY───×───
      │      │              │      │
3: ───XXYY───×──────────────XXYY───×──────────────
""".strip()

    circuit = cirq.Circuit.from_ops(
        swap_network(qubits,
                     lambda i, j, q0, q1: XXYY(q0, q1),
                     fermionic=True,
                     offset=True),
        strategy=cirq.InsertStrategy.EARLIEST)
    assert circuit.to_text_diagram(transpose=True).strip() == """
0    1    2    3
│    │    │    │
│    XXYY─XXYY │
│    │    │    │
│    ×ᶠ───×ᶠ   │
│    │    │    │
XXYY─XXYY XXYY─XXYY
│    │    │    │
×ᶠ───×ᶠ   ×ᶠ───×ᶠ
│    │    │    │
│    XXYY─XXYY │
│    │    │    │
│    ×ᶠ───×ᶠ   │
│    │    │    │
XXYY─XXYY XXYY─XXYY
│    │    │    │
×ᶠ───×ᶠ   ×ᶠ───×ᶠ
│    │    │    │
""".strip()

    n_qubits = 5
    qubits = cirq.LineQubit.range(n_qubits)

    circuit = cirq.Circuit.from_ops(swap_network(qubits,
                                                 lambda i, j, q0, q1: (),
                                                 fermionic=True),
                                    strategy=cirq.InsertStrategy.EARLIEST)
    assert circuit.to_text_diagram(transpose=False).strip() == """
0: ───×ᶠ────────×ᶠ────────×ᶠ───
      │         │         │
1: ───×ᶠ───×ᶠ───×ᶠ───×ᶠ───×ᶠ───
           │         │
2: ───×ᶠ───×ᶠ───×ᶠ───×ᶠ───×ᶠ───
      │         │         │
3: ───×ᶠ───×ᶠ───×ᶠ───×ᶠ───×ᶠ───
           │         │
4: ────────×ᶠ────────×ᶠ────────
""".strip()

    circuit = cirq.Circuit.from_ops(swap_network(qubits,
                                                 lambda i, j, q0, q1: (),
                                                 offset=True),
                                    strategy=cirq.InsertStrategy.EARLIEST)
    assert circuit.to_text_diagram(transpose=True).strip() == """
0 1 2 3 4
│ │ │ │ │
│ ×─× ×─×
│ │ │ │ │
×─× ×─× │
│ │ │ │ │
│ ×─× ×─×
│ │ │ │ │
×─× ×─× │
│ │ │ │ │
│ ×─× ×─×
│ │ │ │ │
""".strip()
コード例 #23
0
def test_swap_network():
    n_qubits = 4
    qubits = cirq.LineQubit.range(n_qubits)

    circuit = cirq.Circuit(
        swap_network(qubits, lambda i, j, q0, q1: cirq.ISWAP(q0, q1)**-1))
    cirq.testing.assert_has_diagram(
        circuit, """
0: ───iSwap──────×──────────────────iSwap──────×──────────────────
      │          │                  │          │
1: ───iSwap^-1───×───iSwap──────×───iSwap^-1───×───iSwap──────×───
                     │          │                  │          │
2: ───iSwap──────×───iSwap^-1───×───iSwap──────×───iSwap^-1───×───
      │          │                  │          │
3: ───iSwap^-1───×──────────────────iSwap^-1───×──────────────────
""")

    circuit = cirq.Circuit(
        swap_network(qubits,
                     lambda i, j, q0, q1: cirq.ISWAP(q0, q1)**-1,
                     fermionic=True,
                     offset=True))
    cirq.testing.assert_has_diagram(circuit,
                                    """
0     1        2        3
│     │        │        │
│     iSwap────iSwap^-1 │
│     │        │        │
│     ×ᶠ───────×ᶠ       │
│     │        │        │
iSwap─iSwap^-1 iSwap────iSwap^-1
│     │        │        │
×ᶠ────×ᶠ       ×ᶠ───────×ᶠ
│     │        │        │
│     iSwap────iSwap^-1 │
│     │        │        │
│     ×ᶠ───────×ᶠ       │
│     │        │        │
iSwap─iSwap^-1 iSwap────iSwap^-1
│     │        │        │
×ᶠ────×ᶠ       ×ᶠ───────×ᶠ
│     │        │        │
""",
                                    transpose=True)

    n_qubits = 5
    qubits = cirq.LineQubit.range(n_qubits)

    circuit = cirq.Circuit(swap_network(qubits,
                                        lambda i, j, q0, q1: (),
                                        fermionic=True),
                           strategy=cirq.InsertStrategy.EARLIEST)
    cirq.testing.assert_has_diagram(
        circuit, """
0: ───×ᶠ────────×ᶠ────────×ᶠ───
      │         │         │
1: ───×ᶠ───×ᶠ───×ᶠ───×ᶠ───×ᶠ───
           │         │
2: ───×ᶠ───×ᶠ───×ᶠ───×ᶠ───×ᶠ───
      │         │         │
3: ───×ᶠ───×ᶠ───×ᶠ───×ᶠ───×ᶠ───
           │         │
4: ────────×ᶠ────────×ᶠ────────
""")

    circuit = cirq.Circuit(swap_network(qubits,
                                        lambda i, j, q0, q1: (),
                                        offset=True),
                           strategy=cirq.InsertStrategy.EARLIEST)
    cirq.testing.assert_has_diagram(circuit,
                                    """
0 1 2 3 4
│ │ │ │ │
│ ×─× ×─×
│ │ │ │ │
×─× ×─× │
│ │ │ │ │
│ ×─× ×─×
│ │ │ │ │
×─× ×─× │
│ │ │ │ │
│ ×─× ×─×
│ │ │ │ │
""",
                                    transpose=True)
コード例 #24
0
def test_reusable():
    ops = swap_network(cirq.LineQubit.range(5))
    assert list(ops) == list(ops)