!pip install cirq==0.8.2
class HHL:
def __init__(
self,
hamiltonian,
initial_state=None,
initial_state_transforms=None,
qpe_register_size=4,
C=None,
t=1
):
self.hamiltonian = hamiltonian
self.initial_state = initial_state
self.initial_state_transforms = initial_state_transforms
self.qpe_register_size = qpe_register_size
self.C = C
self.t = t
const = self.t/np.pi
self.t = const*np.pi
if self.C is None:
self.C = 2*np.pi / (2**self.qpe_register_size * t)
def build_hhl_circuit(self):
self.circuit = cirq.Circuit()
self.ancilla_qubit = cirq.LineQubit(0)
self.qpe_register = [cirq.LineQubit(i) for i in range(1, self.qpe_register_size+1)]
if self.initial_state is None:
self.initial_state_size = int(np.log2(self.hamiltonian.shape[0]))
if self.initial_state_size == 1:
self.initial_state = [cirq.LineQubit(self.qpe_register_size + 1)]
else:
self.initial_state = [cirq.LineQubit(i) for i in range(self.qpe_register_size + 1,self.qpe_register_size + 1 + self.initial_state_size)]
for op in list(self.initial_state_transforms):
self.circuit.append(op(self.initial_state[0]))
self.U = HamiltonianSimulation(_H_=self.hamiltonian, t=self.t)
_qpe_ = QuantumPhaseEstimation(input_qubits=self.initial_state, output_qubits=self.qpe_register, U=self.U)
_qpe_.circuit()
self.circuit += _qpe_.circuit
_eig_val_inv_ = EigenValueInversion(num_qubits=self.qpe_register_size + 1, C=self.C, t=self.t)
self.circuit.append(_eig_val_inv_(*(self.qpe_register + [self.ancilla_qubit])))
self.circuit.append(_qpe_.circuit**(-1))
self.circuit.append(cirq.measure(self.ancilla_qubit,key='a'))
self.circuit.append([
cirq.PhasedXPowGate(
exponent=sympy.Symbol('exponent'),
phase_exponent=sympy.Symbol('phase_exponent')
)(*self.initial_state),
cirq.measure(*self.initial_state, key='m')
])
def simulate(self):
simulator = cirq.Simulator()
params = [{
'exponent': 0.5,
'phase_exponent': -0.5
}, {
'exponent': 0.5,
'phase_exponent': 0
}, {
'exponent': 0,
'phase_exponent': 0
}]
results = simulator.run_sweep(self.circuit, params, repetitions=5000)
for label, result in zip(('X', 'Y', 'Z'), list(results)):
expectation = 1 - 2 * np.mean(
result.measurements['m'][result.measurements['a'] == 1])
print('{} = {}'.format(label, expectation))
class ControlledUnitary(cirq.Gate):
def __init__(self, num_qubits, num_input_qubits, U):
self._num_qubits = num_qubits
self.num_input_qubits = num_input_qubits
self.num_control_qubits = num_qubits - self.num_input_qubits
self.U = U
def num_qubits(self) -> int:
return self._num_qubits
def _decompose_(self, qubits):
qubits = list(qubits)
input_state_qubit = qubits[:self.num_input_qubits]
control_qubits = qubits[self.num_input_qubits:]
for i,q in enumerate(control_qubits):
_pow_ = 2 ** (self.num_control_qubits - i - 1)
yield cirq.ControlledGate(self.U**_pow_)(q, *input_state_qubit)
class QuantumPhaseEstimation:
def __init__(
self,
U,
input_qubits,
num_output_qubits=None,
output_qubits=None,
initial_circuit=[],
measure_or_sim=False
):
self.U = U
self.input_qubits = input_qubits
self.num_input_qubits = len(self.input_qubits)
self.initial_circuit = initial_circuit
self.measure_or_sim = measure_or_sim
if output_qubits is not None:
self.output_qubits = output_qubits
self.num_output_qubits = len(self.output_qubits)
elif num_output_qubits is not None:
self.num_output_qubits = num_output_qubits
self.output_qubits = [cirq.LineQubit(i) for i
in range(self.num_input_qubits,self.num_input_qubits+self.num_output_qubits)]
else:
raise ValueError("Alteast one of num_output_qubits or output_qubits to be specified")
self.num_qubits = self.num_input_qubits+self.num_output_qubits
def inv_qft(self):
self._qft_= QFT(qubits=self.output_qubits)
self._qft_.qft_circuit()
self.QFT_inv_circuit = self._qft_.inv_circuit
def circuit(self):
self.circuit = cirq.Circuit()
self.circuit.append(cirq.H.on_each(*self.output_qubits))
self.qubits = list(self.input_qubits + self.output_qubits)
self.circuit.append(
ControlledUnitary(
self.num_qubits,
self.num_input_qubits,self.U
)(*self.qubits)
)
self.inv_qft()
self.circuit.append(self.QFT_inv_circuit)
if len(self.initial_circuit) > 0 :
self.circuit = self.initial_circuit + self.circuit
def measure(self):
self.circuit.append(cirq.measure(*self.output_qubits,key='m'))
def simulate_circuit(self,measure=True):
sim = cirq.Simulator()
if measure == False:
result = sim.simulate(self.circuit)
else:
result = sim.run(self.circuit, repetitions=1000).histogram(key='m')
return result
class HamiltonianSimulation(cirq.EigenGate, cirq.SingleQubitGate):
def __init__(self, _H_, t, exponent=1.0):
cirq.SingleQubitGate.__init__(self)
cirq.EigenGate.__init__(self, exponent=exponent)
self._H_ = _H_
self.t = t
eigen_vals, eigen_vecs = np.linalg.eigh(self._H_)
self.eigen_components = []
for _lambda_, vec in zip(eigen_vals, eigen_vecs.T):
theta = -_lambda_*t / np.pi
_proj_ = np.outer(vec, np.conj(vec))
self.eigen_components.append((theta, _proj_))
def _with_exponent(self, exponent):
return HamiltonianSimulation(self._H_, self.t, exponent)
def _eigen_components(self):
return self.eigen_components
class EigenValueInversion(cirq.Gate):
def __init__(self, num_qubits, C, t):
super(EigenValueInversion, self)
self._num_qubits = num_qubits
self.C = C
self.t = t
self.N = 2**(num_qubits-1)
def num_qubits(self):
return self._num_qubits
def _decompose_(self, qubits):
base_state = 2**self.N - 1
for eig_val_state in range(self.N):
eig_val_gate = self._ancilla_rotation(eig_val_state)
if (eig_val_state != 0):
base_state = eig_val_state - 1
qubits_to_flip = eig_val_state ^ base_state
for q in qubits[-2::-1]:
if qubits_to_flip % 2 == 1:
yield cirq.X(q)
qubits_to_flip >>= 1
eig_val_gate = cirq.ControlledGate(eig_val_gate)
yield eig_val_gate(*qubits)
def _ancilla_rotation(self, eig_val_state):
if eig_val_state == 0:
eig_val_state = self.N
theta = 2*math.asin(self.C * self.N * self.t / (2*np.pi * eig_val_state))
return cirq.ry(theta)
class QFT:
def __init__(
self,
signal_length=16,
basis_to_transform='',
validate_inverse_fourier=False,
qubits=None
):
self.signal_length = signal_length
self.basis_to_transform = basis_to_transform
if qubits is None:
self.num_qubits = int(np.log2(signal_length))
self.qubits = [cirq.LineQubit(i) for i in range(self.num_qubits)]
else:
self.qubits = qubits
self.num_qubits = len(self.qubits)
self.qubit_index = 0
self.input_circuit = cirq.Circuit()
self.validate_inverse_fourier = validate_inverse_fourier
self.circuit = cirq.Circuit()
self.inv_circuit = cirq.Circuit()
for k, q_s in enumerate(self.basis_to_transform):
if int(q_s) == 1:
self.input_circuit.append(cirq.X(self.qubits[k]))
def qft_circuit_iter(self):
if self.qubit_index > 0:
for j in range(self.qubit_index):
diff = self.qubit_index - j + 1
rotation_to_apply = -2.0 / (2.0 ** diff)
self.circuit.append(
cirq.CZ(
self.qubits[self.qubit_index],
self.qubits[j]
) ** rotation_to_apply
)
self.circuit.append(cirq.H(self.qubits[self.qubit_index]))
self.qubit_index += 1
def qft_circuit(self):
while self.qubit_index < self.num_qubits:
self.qft_circuit_iter()
self.swap_qubits()
self.inv_circuit = cirq.inverse(self.circuit.copy())
def swap_qubits(self):
for i in range(self.num_qubits // 2):
self.circuit.append(cirq.SWAP(self.qubits[i], self.qubits[self.num_qubits - i - 1]))
def simulate_circuit(self):
sim = cirq.Simulator()
result = sim.simulate(self.circuit)
return result
A = np.array([
[4.30213466 - 6.01593490e-08j, 0.23531802 + 9.34386156e-01j],
[0.23531882 - 9.34388383e-01j, 0.58386534 + 6.01593489e-08j]
])
t = 0.358166 * np.pi
C = None
qpe_register_size = 4
initial_state_transforms = [cirq.rx(1.276359), cirq.rz(1276359)]
_hhl_ = HHL(
hamiltonian=A,
initial_state_transforms=initial_state_transforms,
qpe_register_size=4
)
_hhl_.build_hhl_circuit()
_hhl_.simulate()
=> X = -0.38055555555555554
=> Y = 0.3121621621621622
=> Z = -0.8750821827744906
▼ ワンコインAI無料お試し
▼ DeepRecommendから限定情報を受け取る