예제 #1
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.Rot11Gate(rads=-0.5 * self.orbital_energies[i] * time).on(
            control_qubit, 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 Rot111Gate(rads=-2 * self.hamiltonian.two_body[p, q] *
                             time).on(control_qubit, 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.Rot11Gate(rads=-0.5 * self.orbital_energies[i] * time).on(
            control_qubit, qubits[i]) for i in range(n_qubits))

        # Apply phase from constant term
        yield cirq.RotZGate(rads=-self.hamiltonian.constant *
                            time).on(control_qubit)
예제 #2
0
def test_rot_gates_eq():
    eq = cirq.testing.EqualsTester()
    gates = [
        cirq.RotXGate, cirq.RotYGate, cirq.RotZGate, cirq.CNotGate,
        cirq.Rot11Gate
    ]
    for gate in gates:
        eq.add_equality_group(gate(half_turns=3.5), gate(half_turns=-0.5),
                              gate(rads=-np.pi / 2), gate(degs=-90))
        eq.make_equality_group(lambda: gate(half_turns=0))
        eq.make_equality_group(lambda: gate(half_turns=0.5))

    eq.add_equality_group(cirq.RotXGate(), cirq.RotXGate(half_turns=1), cirq.X)
    eq.add_equality_group(cirq.RotYGate(), cirq.RotYGate(half_turns=1), cirq.Y)
    eq.add_equality_group(cirq.RotZGate(), cirq.RotZGate(half_turns=1), cirq.Z)
    eq.add_equality_group(
        cirq.RotZGate(half_turns=1, global_shift_in_half_turns=-0.5),
        cirq.RotZGate(half_turns=5, global_shift_in_half_turns=-0.5))
    eq.add_equality_group(
        cirq.RotZGate(half_turns=3, global_shift_in_half_turns=-0.5))
    eq.add_equality_group(
        cirq.RotZGate(half_turns=1, global_shift_in_half_turns=-0.1))
    eq.add_equality_group(
        cirq.RotZGate(half_turns=5, global_shift_in_half_turns=-0.1))
    eq.add_equality_group(cirq.CNotGate(), cirq.CNotGate(half_turns=1),
                          cirq.CNOT)
    eq.add_equality_group(cirq.Rot11Gate(), cirq.Rot11Gate(half_turns=1),
                          cirq.CZ)
예제 #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)

        # 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.Rot11Gate(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: 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))

            # 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.RotZGate(rads=-self.hamiltonian.constant *
                            time).on(control_qubit)
예제 #4
0
def rot_11_layer(el_jr, el_jc, half_turns):
    """Yields rotations about |11> conditioned on the jr and jc fields."""
    gate = cirq.Rot11Gate(half_turns=half_turns)
    for i, jr_row in enumerate(el_jr):
        for j, jr_ij in enumerate(jr_row):
            if jr_ij == -1:
                yield cirq.X(cirq.GridQubit(i, j))
                yield cirq.X(cirq.GridQubit(i + 1, j))
            yield gate(cirq.GridQubit(i, j), cirq.GridQubit(i + 1, j))
            if jr_ij == -1:
                yield cirq.X(cirq.GridQubit(i, j))
                yield cirq.X(cirq.GridQubit(i + 1, j))
                pass
            pass
        pass
    pass

    for i, jc_row in enumerate(el_jc):
        for j, jc_ij in enumerate(jc_row):
            if jc_ij == 1:
                yield gate(cirq.GridQubit(i, j), cirq.GridQubit(i, j + 1))
                pass
            pass
        pass
    pass
예제 #5
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 ControlledXXYYGate(
                duration=self.hamiltonian.one_body[p, q].real * time).on(
                    control_qubit, a, b)
            yield ControlledYXXYGate(
                duration=self.hamiltonian.one_body[p, q].imag * time).on(
                    control_qubit, a, b)
            yield Rot111Gate(rads=-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 (cirq.Rot11Gate(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.RotZGate(rads=-self.hamiltonian.constant *
                            time).on(control_qubit)
예제 #6
0
def test_cz_matrix():
    assert np.allclose(
        cirq.Rot11Gate(half_turns=1).matrix(),
        np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, -1]]))

    assert np.allclose(
        cirq.Rot11Gate(half_turns=0.5).matrix(),
        np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1j]]))

    assert np.allclose(
        cirq.Rot11Gate(half_turns=0).matrix(),
        np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]))

    assert np.allclose(
        cirq.Rot11Gate(half_turns=-0.5).matrix(),
        np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, -1j]]))
예제 #7
0
 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)
    def default_decompose(self, qubits):
        a, b, c, d = qubits

        weights_to_exponents = (self._exponent / 4.) * numpy.array(
            [[1, -1, 1], [1, 1, -1], [-1, 1, 1]])
        exponents = weights_to_exponents.dot(self.weights)

        basis_change = list(
            cirq.flatten_op_tree([
                cirq.CNOT(b, a),
                cirq.CNOT(c, b),
                cirq.CNOT(d, c),
                cirq.CNOT(c, b),
                cirq.CNOT(b, a),
                cirq.CNOT(a, b),
                cirq.CNOT(b, c),
                cirq.CNOT(a, b),
                [cirq.X(c), cirq.X(d)],
                [cirq.CNOT(c, d), cirq.CNOT(d, c)],
                [cirq.X(c), cirq.X(d)],
            ]))

        controlled_Zs = list(
            cirq.flatten_op_tree([
                cirq.Rot11Gate(half_turns=exponents[0])(b, c),
                cirq.CNOT(a, b),
                cirq.Rot11Gate(half_turns=exponents[1])(b, c),
                cirq.CNOT(b, a),
                cirq.CNOT(a, b),
                cirq.Rot11Gate(half_turns=exponents[2])(b, c)
            ]))

        controlled_swaps = [
            [cirq.CNOT(c, d), cirq.H(c)],
            cirq.CNOT(d, c),
            controlled_Zs,
            cirq.CNOT(d, c),
            [op.inverse() for op in reversed(controlled_Zs)],
            [cirq.H(c), cirq.CNOT(c, d)],
        ]

        yield basis_change
        yield controlled_swaps
        yield basis_change[::-1]
예제 #9
0
 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 XXYYGate(half_turns=t_symbol).on(a, b)
     if w_symbol in param_set:
         yield YXXYGate(half_turns=w_symbol).on(a, b)
     if v_symbol in param_set:
         yield cirq.Rot11Gate(half_turns=v_symbol).on(a, b)
예제 #10
0
 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)
예제 #11
0
def test_not_decompose_partial_czs():
    circuit = cirq.Circuit.from_ops(
        cirq.Rot11Gate(half_turns=0.1)(*cirq.LineQubit.range(2)), )

    optimizer = cirq.MergeInteractions(allow_partial_czs=True)
    optimizer.optimize_circuit(circuit)

    cz_gates = [
        op.gate for op in circuit.all_operations()
        if isinstance(op, cirq.GateOperation)
        and isinstance(op.gate, cirq.Rot11Gate)
    ]
    num_full_cz = sum(1 for cz in cz_gates if cz.half_turns == 1)
    num_part_cz = sum(1 for cz in cz_gates if cz.half_turns != 1)
    assert num_full_cz == 0
    assert num_part_cz == 1
예제 #12
0
def rot_11_layer(jr, jc, half_turns):
    """Yeilds rotations about |11> conditioned on the jr and jc fields."""
    gate = cirq.Rot11Gate(half_turns=0.5)
    print(gate.matrix())
    for i, jr_row in enumerate(jr):
        for j, jr_ij in enumerate(jr_row):

            if jr_ij == -1:
                yield cirq.X(cirq.GridQubit(i, j))
                yield cirq.X(cirq.GridQubit(i + 1, j))
            yield gate(cirq.GridQubit(i, j), cirq.GridQubit(i + 1, j))
        if jr_ij == -1:
            yield cirq.X(cirq.GridQubit(i, j))
            yield cirq.X(cirq.GridQubit(i + 1, j))
    for i, jc_row in enumerate(jc):
        for j, jc_ij in enumerate(jc_row):
            if jc_ij == 1:
                yield gate(cirq.GridQubit(i, j), cirq.GridQubit(i, j + 1))
예제 #13
0
 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)
예제 #14
0
def test_cz_extrapolate():
    assert cirq.Rot11Gate(half_turns=1)**0.5 == cirq.Rot11Gate(half_turns=0.5)
    assert cirq.CZ**-0.25 == cirq.Rot11Gate(half_turns=1.75)
예제 #15
0
def test_cz_repr():
    assert repr(cirq.Rot11Gate()) == 'cirq.CZ'
    assert repr(cirq.Rot11Gate(half_turns=0.5)) == '(cirq.CZ**0.5)'
    assert repr(cirq.Rot11Gate(half_turns=-0.25)) == '(cirq.CZ**-0.25)'
예제 #16
0
def test_cz_str():
    assert str(cirq.Rot11Gate()) == 'CZ'
    assert str(cirq.Rot11Gate(half_turns=0.5)) == 'CZ**0.5'
    assert str(cirq.Rot11Gate(half_turns=-0.25)) == 'CZ**-0.25'
예제 #17
0
def test_cz_init():
    assert cirq.Rot11Gate(half_turns=0.5).half_turns == 0.5
    assert cirq.Rot11Gate(half_turns=5).half_turns == 1
 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)
예제 #19
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)
예제 #20
0
def test_cz_extrapolate():
    assert cirq.Rot11Gate(
        half_turns=1).extrapolate_effect(0.5) == cirq.Rot11Gate(half_turns=0.5)
    assert cirq.CZ**-0.25 == cirq.Rot11Gate(half_turns=1.75)
예제 #21
0
 def two_body_interaction(p, q, a, b) -> cirq.OP_TREE:
     yield cirq.Rot11Gate(rads=-2 * self.hamiltonian.two_body[p, q] *
                          time).on(a, b)
예제 #22
0
            cirq.Z(a)**-v,
            cirq.Z(b)**-v,
        ))


def test_optimizes_single_iswap():
    a, b = cirq.LineQubit.range(2)
    c = cirq.Circuit.from_ops(cirq.ISWAP(a, b))
    assert_optimization_not_broken(c)
    cirq.MergeInteractions().optimize_circuit(c)
    assert len([1 for op in c.all_operations() if len(op.qubits) == 2]) == 2


@pytest.mark.parametrize(
    'circuit', (cirq.Circuit.from_ops(
        cirq.Rot11Gate(half_turns=0.1)(*cirq.LineQubit.range(2)), ),
                cirq.Circuit.from_ops(
                    cirq.Rot11Gate(half_turns=0.2)(*cirq.LineQubit.range(2)),
                    cirq.Rot11Gate(half_turns=0.3)(*cirq.LineQubit.range(2)),
                )))
def test_decompose_partial_czs(circuit):
    optimizer = cirq.MergeInteractions(allow_partial_czs=False)
    optimizer.optimize_circuit(circuit)

    cz_gates = [
        op.gate for op in circuit.all_operations()
        if isinstance(op, cirq.GateOperation)
        and isinstance(op.gate, cirq.Rot11Gate)
    ]
    num_full_cz = sum(1 for cz in cz_gates if cz.half_turns == 1)
    num_part_cz = sum(1 for cz in cz_gates if cz.half_turns != 1)