from qubiter.device_specific.Qubiter_to_AnyQasm import *
import qubiter.utilities_gen as utg
[docs]class Qubiter_to_IBMqasm(Qubiter_to_AnyQasm):
"""
See docstring of parent class Qubiter_to_AnyQasm.
If input c_to_tars = None, all CNOTs allowed.
References
----------
1. https://github.com/Qiskit
Attributes
----------
"""
[docs] def __init__(self, file_prefix, num_qbits, **kwargs):
"""
Constructor
Parameters
----------
Returns
-------
"""
Qubiter_to_AnyQasm.__init__(self, file_prefix, num_qbits, **kwargs)
[docs] def write_prelude(self):
"""
Writes IBM qasm opening statements before calls to use_ methods for
gates.
Returns
-------
None
"""
s = "import numpy as np\n"
s += 'from qiskit import QuantumCircuit\n'
s += 'from qiskit import ClassicalRegister, QuantumRegister\n'
s += 'from qiskit import execute\n\n\n'
s += "q = QuantumRegister(" + str(self.num_qbits) + ", 'q')\n"
s += 'ckt = QuantumCircuit(q)'
self.write(s + '\n')
[docs] def write_ending(self):
"""
Writes IBM qasm ending statements after calls to use_ methods for
gates.
Returns
-------
None
"""
pass
[docs] @staticmethod
def qasm_line_for_rot(arr, tar_bit_pos):
"""
This function returns a string for an IBM qasm file line for a one
qubit rotation.
Parameters
----------
arr : np.array
the matrix of the rotation
tar_bit_pos : int
target bit position at which rotation occurs.
Returns
-------
str
"""
# U(\theta,\phi,\lambda) := R_z(\phi)R_y(\theta)R_z(\lambda)
# R_y(\theta)=\mathrm{exp}(-i\theta Y/2)
# R_z(\phi)=\mathrm{exp}(-i\phi Z/2)
# excerpt from qelib1.inc
# // 3-parameter 2-pulse single qubit gate
# gate u3(theta,phi,lambda) q { U(theta,phi,lambda) q; }
# // 2-parameter 1-pulse single qubit gate
# gate u2(phi,lambda) q { U(pi/2,phi,lambda) q; }
# // 1-parameter 0-pulse single qubit gate
# gate u1(lambda) q { U(0,0,lambda) q; }
# // controlled-NOT
# gate cx c,t { CX c,t; }
# // idle gate (identity)
# gate id a { U(0,0,0) a; }
delta, left_rads, center_rads, right_rads = \
UnitaryMat.u2_zyz_decomp(arr)
phi = -2*left_rads
theta = -2*center_rads
lam = -2*right_rads
if abs(phi) < 1e-6 and abs(theta) < 1e-6:
line_str = "ckt.u1(" + str(lam)
elif abs(theta - np.pi/2) < 1e-6:
line_str = "ckt.u2(" + str(phi) + ", " + str(lam)
else:
line_str = "ckt.u3(" + str(theta) + ", " + \
str(phi) + ", " + str(lam)
line_str += "), q[" + str(tar_bit_pos) + "])\n"
return line_str
[docs] def use_HAD2(self, tar_bit_pos, controls):
"""
Writes line in IBM qasm file corresponding to an English file line
of type: HAD2 with no controls.
Parameters
----------
tar_bit_pos : int
controls : Controls
Returns
-------
None
"""
assert len(controls.bit_pos) == 0
self.aqasm_out.write("ckt.h(q[" + str(tar_bit_pos) + "])\n")
if self.write_qubiter_files:
self.qbtr_wr.write_controlled_one_qbit_gate(tar_bit_pos, controls,
OneQubitGate.had2)
[docs] def use_NOTA(self, bla_str):
"""
Writes line in IBM qasm file corresponding to an English file line
of type: NOTA
Parameters
----------
bla_str : str
Returns
-------
None
"""
self.aqasm_out.write("# " + bla_str + "\n")
if self.write_qubiter_files:
self.qbtr_wr.write_NOTA(bla_str)
[docs] def use_PHAS(self, angle_rads, tar_bit_pos, controls):
"""
If called for a controlled phase, this function will halt execution
of program. If it's just a global phase with no controls,
the function will comment the phase out in the output files (IBM
qasm and output Qubiter English and Picture files.) and move on to
the next line.
Parameters
----------
angle_rads : float
tar_bit_pos : int
controls : Controls
Returns
-------
None
"""
def degs_str(x):
return x if isinstance(x, str) else str(x*180/np.pi)
if controls.bit_pos_to_kind:
assert False, "No PHAS lines with controls allowed"
else:
bla_str = 'PHAS\t' + degs_str(angle_rads) +\
'\tAT\t' + str(tar_bit_pos)
self.aqasm_out.write("# " + bla_str + "\n")
if self.write_qubiter_files:
self.qbtr_wr.write_NOTA(bla_str)
[docs] def use_P_PH(self, projection_bit, angle_rads, tar_bit_pos, controls):
"""
Writes line in IBM qasm file corresponding to an English file line
of type: P0PH or P1PH with 0 or 1 controls.
Parameters
----------
projection_bit : int
angle_rads : float
tar_bit_pos : int
controls : Controls
Returns
-------
None
"""
assert isinstance(angle_rads, float),\
'At present, IBM qasm does not support variable angles'
assert not self.strict_mode
num_trols = len(controls.bit_pos)
assert num_trols in [0, 1]
line_str = "ckt."
if num_trols == 0:
assert projection_bit == 1, \
'exp(j*P_0*alp) not implemented in IBM qasm. ' +\
'You can use exp(j*P_0*alp)=sig_x*exp(j*P_1*alp)*sig_x'
line_str += 'u1('
else: # num_trols == 1
trol_bit_pos = controls.bit_pos[0]
trol_type = controls.bit_pos_to_kind[trol_bit_pos]
second_bit = 1 if trol_type else 0
if projection_bit == 0:
if second_bit == 0:
line_str += 'CPHASE00('
assert False, 'this gate not implemented in IBM qasm'
else:
line_str += 'CPHASE01('
assert False, 'this gate not implemented in IBM qasm'
elif projection_bit == 1:
if second_bit == 0:
line_str += 'CPHASE10('
assert False, 'this gate not implemented in IBM qasm'
else:
line_str += 'cu1('
else:
assert False
if isinstance(angle_rads, float):
ibm_rads = angle_rads
elif isinstance(angle_rads, str):
ibm_rads = self.new_var_name(angle_rads)
else:
assert False
line_str += str(ibm_rads)
if num_trols == 0:
line_str += ', q[' + str(tar_bit_pos)
else: # num_trols == 1:
line_str += ', q[' + str(controls.bit_pos[0])
line_str += '], q[' + str(tar_bit_pos)
line_str += "])\n"
self.aqasm_out.write(line_str)
if self.write_qubiter_files:
if projection_bit == 0:
u2_fun = OneQubitGate.P_0_phase_fac
elif projection_bit == 1:
u2_fun = OneQubitGate.P_1_phase_fac
else:
assert False
self.qbtr_wr.write_controlled_one_qbit_gate(
tar_bit_pos, controls, u2_fun, [angle_rads])
[docs] def use_PRINT(self, style, line_num):
"""
Writes line in IBM qasm file corresponding to an English file line
of type: PRINT
Parameters
----------
style : str
line_num : int
Returns
-------
None
"""
str1 = 'PRINT\t' + style
self.aqasm_out.write("# " + str1 + "\n")
if self.write_qubiter_files:
self.qbtr_wr.write_NOTA(str1)
[docs] def use_ROTA(self, axis, angle_rads, tar_bit_pos, controls):
"""
Writes line in IBM qasm file corresponding to an English file line
of type: ROTX, ROTY or ROTZ with no controls.
Parameters
----------
axis : int
angle_rads : float
tar_bit_pos : int
controls : Controls
Returns
-------
None
"""
assert isinstance(angle_rads, float),\
'At present, IBM qasm does not support variable angles'
assert len(controls.bit_pos) == 0
arr = OneQubitGate.rot_ax(angle_rads, axis)
line_str = Qubiter_to_IBMqasm.qasm_line_for_rot(arr, tar_bit_pos)
self.aqasm_out.write(line_str)
if self.write_qubiter_files:
self.qbtr_wr.write_controlled_one_qbit_gate(tar_bit_pos, controls,
OneQubitGate.rot_ax, [angle_rads, axis])
[docs] def use_ROTN(self, angle_x_rads, angle_y_rads, angle_z_rads,
tar_bit_pos, controls):
"""
Writes line in IBM qasm file corresponding to an English file line
of type: ROTN with no controls.
Parameters
----------
angle_x_rads : float
angle_y_rads : float
angle_z_rads : float
tar_bit_pos : int
controls : Controls
Returns
-------
None
"""
assert len(controls.bit_pos) == 0
rad_ang_list = [angle_x_rads, angle_y_rads, angle_z_rads]
assert utg.all_floats(rad_ang_list), \
'At present, IBM qasm does not support variable angles'
arr = OneQubitGate.rot(*rad_ang_list)
line_str = Qubiter_to_IBMqasm.qasm_line_for_rot(arr, tar_bit_pos)
self.aqasm_out.write(line_str)
if self.write_qubiter_files:
self.qbtr_wr.write_controlled_one_qbit_gate(tar_bit_pos, controls,
OneQubitGate.rot, rad_ang_list)
[docs] def use_SIG(self, axis, tar_bit_pos, controls):
"""
Writes line in IBM qasm file corresponding to an English file line
of type: SIGX, SIGY or SIGZ with no controls, or else SIGX with one
True control (i.e., simple CNOT).
Parameters
----------
axis : int
tar_bit_pos : int
controls : Controls
Returns
-------
None
"""
num_trols = len(controls.bit_pos)
assert num_trols in [0, 1]
if num_trols == 1:
assert axis == 1
assert controls.bit_pos_to_kind[controls.bit_pos[0]] == True
if num_trols == 0:
if axis == 1:
prefix = "ckt.x(q["
elif axis == 2:
prefix = "ckt.y(q["
elif axis == 3:
prefix = "ckt.z(q["
else:
assert False
self.aqasm_out.write(prefix + str(tar_bit_pos) + "])\n")
if self.write_qubiter_files:
if axis == 1:
u2_fun = OneQubitGate.sigx
elif axis == 2:
u2_fun = OneQubitGate.sigy
elif axis == 3:
u2_fun = OneQubitGate.sigz
else:
assert False
self.qbtr_wr.write_controlled_one_qbit_gate(tar_bit_pos,
controls, u2_fun)
else: # num_trols == 1
tar_pos = tar_bit_pos
trol_pos = controls.bit_pos[0]
if not self.c_to_tars or tar_pos in self.c_to_tars[trol_pos]:
self.aqasm_out.write("ckt.cx(q[" + str(trol_pos) + "], "
"q[" + str(tar_pos) + "])\n")
if self.write_qubiter_files:
self.qbtr_wr.write_cnot(trol_pos, tar_pos)
else:
assert False, "Forbidden CNOT detected: " \
+ str(trol_pos) + "->" + str(tar_pos) \
+ " in line " + str(self.line_count) \
+ ". Use class ForbiddenCNotExpander " \
+ "before attempting translation to IBM qasm."
[docs] def use_SWAP(self, bit1, bit2, controls):
"""
Writes line in IBM qasm file corresponding to an English file line
of type: SWAP with no controls.
Parameters
----------
bit1 : int
bit2 : int
controls : Controls
Returns
-------
None
"""
assert not self.strict_mode
assert len(controls.bit_pos) == 0
line_str = 'ckt.swap(q[' + \
str(bit1) + "], q[" + str(bit2) + "])\n"
self.aqasm_out.write(line_str)
if self.write_qubiter_files:
self.qbtr_wr.write_controlled_qbit_swap(bit1, bit2, controls)
if __name__ == "__main__":
import qubiter.device_specific.chip_couplings_ibm as ibm
def main():
file_prefix = "qbtr2ibm_test"
aqasm_name = 'IBMqasm'
num_qbits = 5
c_to_tars = ibm.ibmq5YorktownTenerife_c_to_tars
Qubiter_to_IBMqasm(file_prefix, num_qbits, aqasm_name=aqasm_name,
c_to_tars=c_to_tars, write_qubiter_files=True)
main()