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 (rot11(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 rot111(-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 (rot11(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.Rz(rads=-self.hamiltonian.constant * time).on(control_qubit)
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)
def one_and_two_body_interaction_reverse_order(p, q, a, b) -> cirq.OP_TREE: yield rot11(rads=-self.hamiltonian.two_body[p, q] * time).on(a, b) yield Ryxxy(0.5 * self.hamiltonian.one_body[p, q].imag * time).on( a, b) yield Rxxyy(0.5 * self.hamiltonian.one_body[p, q].real * time).on( a, b)
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)
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)
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)
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)