When performing quantum calculations, you may want to get the initial state to the desired shape. Especially, it seems to be necessary for quantum neural networks.
what if
\frac{|000>+|001>-|010>+|011>-|100>-|101>+|110>+|111>}{2 \sqrt{2}}
Wouldn't it be convenient if you could quickly find the combination of gates to make? The idea to achieve this is Quantum Hypergraph State.
See Quantum Hypergraph states for more information.
Quantum Hypergraph states
I would like to briefly explain Quantum Hypergraph states.
\frac{i_0|000>+i_1|001>+i_2|010>+i_3|011>+i_4|100>+i_5|101>+i_6|110>+i_7|111>}{2 \sqrt{2}} \\
i_k = -1 \ or \ 1
For 3qubit, this makes all coefficients 1.
\frac{|000>+|001>-|010>+|011>-|100>-|101>+|110>+|111>}{2 \sqrt{2}}
\frac{|000>+|001>+|010>-|011>+|100>+|101>+|110>+|111>}{2 \sqrt{2}}
\frac{|000>+|001>+|010>+|011>+|100>+|101>+|110>-|111>}{2 \sqrt{2}}
\frac{|000>+|001>+|010>+|011>+|100>+|101>+|110>+|111>}{2 \sqrt{2}}
This is the end of circuit construction.
Code
The Code is as follows. To be honest, I'm not good at Python, so there may be some waste. I would appreciate it if you could tell me if there is an efficient way to write. By the way, this time it is up to 3qubit, but I think that you can increase it as much as you like.
python
# matplotlib inline
# coding: utf-8
import numpy as np
from math import log2
from copy import deepcopy
from qiskit import QuantumCircuit, QuantumRegister
from qiskit.quantum_info.operators import Operator
import matplotlib.pyplot as plt
def count_ones_by_bin(num):
bin_num = bin(num)[2:]
count = 0
for i in bin_num:
count += int(i)
return count
class QuantumHypergraphState:
def __init__(self, numqubits, states, qubit_index=None):
''' make Quantum HyperGraph State in circuit
:param circuit:
:param numqubits: maximum 3
:param states:
'''
self.numqubits = numqubits
self.states = deepcopy(states)
if qubit_index is None:
self.index = [i for i in range(numqubits)]
else:
self.index = qubit_index
def bin_length(self, num):
bin_num = bin(num)[2:]
dif_len = self.numqubits - len(bin_num)
for i in range(dif_len):
bin_num = '0' + bin_num
return bin_num
def get_z_tgt(self, num):
bin_num = self.bin_length(num)[::-1]
z_tgt = []
for i in range(len(bin_num)):
if int(bin_num[i]) == 1:
z_tgt.append(i)
return z_tgt
def tgt_0(self, num, tgt):
"""
e.g. tgt = [0]
num = 011
"""
bin_num = self.bin_length(num)[::-1] # 011
count = 0
for i in range(len(bin_num)):
if i in tgt:
count += int(bin_num[i])
if count == len(tgt):
return True
else:
return False
def renew_states(self, tgt):
for st in range(len(self.states)):
if self.tgt_0(st, tgt):
self.states[st] *= -1
def get_tgt_list(self, idx_list):
tgt_list = []
for i in range(len(idx_list)):
tgt_list.append(self.index[idx_list[i]])
return tgt_list
def construct_circuit(self, circuit, inverse=False):
ccz = Operator([[1, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 0, 0, 0],
[0, 0, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 1, 0, 0, 0, 0],
[0, 0, 0, 0, 1, 0, 0, 0],
[0, 0, 0, 0, 0, 1, 0, 0],
[0, 0, 0, 0, 0, 0, 1, 0],
[0, 0, 0, 0, 0, 0, 0, -1]])
if inverse:
gate_list = []
else:
circuit.h(self.index)
for num in range(1, self.numqubits + 1):
#Loop for states
if num == 1:
for st in range(len(self.states)):
if count_ones_by_bin(st) == num:
if self.states[st] == -1:
idx = int(log2(st))
tgt = self.index[idx]
if inverse:
gate_list.append(['z', [tgt]])
else:
circuit.z(tgt)
self.renew_states([idx])
elif num == 2:
for st in range(len(self.states)):
if count_ones_by_bin(st) == num:
if self.states[st] == -1:
idx_list = self.get_z_tgt(st)
tgt_list = self.get_tgt_list(idx_list)
if inverse:
gate_list.append(['cz', tgt_list])
else:
circuit.cz(tgt_list[0], tgt_list[1])
self.renew_states(idx_list)
else:
for st in range(len(self.states)):
if count_ones_by_bin(st) == num:
if self.states[st] == -1:
idx_list = self.get_z_tgt(st)
tgt_list = self.get_tgt_list(idx_list)
if inverse:
gate_list.append(['ccz', tgt_list])
else:
circuit.unitary(ccz, self.index, label='ccz')
self.renew_states(idx_list)
if inverse:
gate_list = gate_list[::-1]
for gate in gate_list:
if gate[0] == 'ccz':
circuit.unitary(ccz, self.index, label='ccz')
if gate[0] == 'cz':
circuit.cz(gate[1][0], gate[1][1])
if gate[0] == 'z':
circuit.z(gate[1][0])
# circuit.h(self.index)
circuit.x(self.index)
return circuit
else:
return circuit
def draw(self):
print(self.qc.draw(output='mpl'))
that's all. Thank you very much.
I was spitting out some errors so I updated it: 2020/04/12
Recommended Posts