| 7 | |
| 8 | |
| 9 | class HHL: |
| 10 | |
| 11 | def __init__(self, hamiltonian, initial_state=None, initial_state_transforms=None, qpe_register_size=4, C=None, t=1): |
| 12 | """ |
| 13 | :param hamiltonian: Hamiltonian to Simulate |
| 14 | :param C: hyper parameter to Eigen Value Inversion |
| 15 | :param t: Time for which Hamiltonian is simulated |
| 16 | :param initial_state: |b> |
| 17 | """ |
| 18 | self.hamiltonian = hamiltonian |
| 19 | self.initial_state = initial_state |
| 20 | self.initial_state_transforms = initial_state_transforms |
| 21 | self.qpe_register_size = qpe_register_size |
| 22 | self.C = C |
| 23 | self.t = t |
| 24 | |
| 25 | const = self.t/np.pi |
| 26 | self.t = const*np.pi |
| 27 | if self.C is None: |
| 28 | self.C = 2*np.pi / (2**self.qpe_register_size * t) |
| 29 | |
| 30 | |
| 31 | def build_hhl_circuit(self): |
| 32 | self.circuit = cirq.Circuit() |
| 33 | self.ancilla_qubit = cirq.LineQubit(0) |
| 34 | self.qpe_register = [cirq.LineQubit(i) for i in range(1, self.qpe_register_size+1)] |
| 35 | if self.initial_state is None: |
| 36 | self.initial_state_size = int(np.log2(self.hamiltonian.shape[0])) |
| 37 | if self.initial_state_size == 1: |
| 38 | self.initial_state = [cirq.LineQubit(self.qpe_register_size + 1)] |
| 39 | else: |
| 40 | self.initial_state = [cirq.LineQubit(i) for i in range(self.qpe_register_size + 1, |
| 41 | self.qpe_register_size + 1 + self.initial_state_size)] |
| 42 | |
| 43 | for op in list(self.initial_state_transforms): |
| 44 | print(op) |
| 45 | self.circuit.append(op(self.initial_state[0])) |
| 46 | |
| 47 | # Define Unitary Operator simulating the Hamiltonian |
| 48 | self.U = HamiltonianSimulation(_H_=self.hamiltonian, t=self.t) |
| 49 | # Perform Quantum Phase Estimation |
| 50 | _qpe_ = QuantumPhaseEstimation(input_qubits=self.initial_state, |
| 51 | output_qubits=self.qpe_register, U=self.U) |
| 52 | _qpe_.circuit() |
| 53 | print(dir(_qpe_)) |
| 54 | print('CIRCUIT',_qpe_.circuit) |
| 55 | self.circuit += _qpe_.circuit |
| 56 | # Perform EigenValue Inversion |
| 57 | _eig_val_inv_ = EigenValueInversion(num_qubits=self.qpe_register_size + 1, C=self.C, t=self.t) |
| 58 | self.circuit.append(_eig_val_inv_(*(self.qpe_register + [self.ancilla_qubit]))) |
| 59 | #Uncompute the qpe_register to |0..0> state |
| 60 | print(self.circuit) |
| 61 | #print(_qpe_.circuit**(-1)) |
| 62 | self.circuit.append(_qpe_.circuit**(-1)) |
| 63 | self.circuit.append(cirq.measure(self.ancilla_qubit,key='a')) |
| 64 | self.circuit.append([ |
| 65 | cirq.PhasedXPowGate( |
| 66 | exponent=sympy.Symbol('exponent'), |