Skip to content

Commit

Permalink
Merge pull request #20 from Zhaoyilunnn/master
Browse files Browse the repository at this point in the history
1. Add runtime_job_id 2. Add back `from_openqasm` to ensure backward compatibility
  • Loading branch information
ScQ-Cloud authored Jun 8, 2023
2 parents 81a35b5 + b4327d4 commit 93edf5b
Show file tree
Hide file tree
Showing 4 changed files with 223 additions and 88 deletions.
198 changes: 166 additions & 32 deletions src/quafu/circuits/quantum_circuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ class QuantumCircuit(object):
def __init__(self, num: int):
"""
Initialize a QuantumCircuit object
Args:
Args:
num (int): Total qubit number used
"""
self.num = num
Expand All @@ -32,7 +32,7 @@ def layered_circuit(self) -> np.ndarray:
"""
Make layered circuit from the gate sequence self.gates.
Returns:
Returns:
A layered list with left justed circuit.
"""
num = self.num
Expand Down Expand Up @@ -121,7 +121,7 @@ def draw_circuit(self, width : int=4, return_str : bool=False):
if isinstance(gate, ControlledGate): #Controlled-Multiqubit gate
for ctrl in gate.ctrls:
printlist[reduce_map[ctrl] * 2, l] = "*"

if gate.targ_name == "SWAP":
printlist[reduce_map[gate.targs[0]] * 2, l] = "x"
printlist[reduce_map[gate.targs[1]] * 2, l] = "x"
Expand All @@ -135,7 +135,7 @@ def draw_circuit(self, width : int=4, return_str : bool=False):
else:
printlist[tq1 + tq2, l] = gate.symbol
maxlen = max(maxlen, len(gate.symbol) + width)

else: #Multiqubit gate
if gate.name == "SWAP":
printlist[q1 * 2, l] = "x"
Expand All @@ -151,7 +151,7 @@ def draw_circuit(self, width : int=4, return_str : bool=False):
q2 = reduce_map[max(pos)]
printlist[2 * q1:2 * q2 + 1, l] = "||"
maxlen = max(maxlen, len("||"))


printlist[-1, l] = maxlen

Expand All @@ -167,18 +167,153 @@ def draw_circuit(self, width : int=4, return_str : bool=False):
circuitstr.append("".ljust(6) + "".join(
[printlist[j, l].center(int(printlist[-1, l]), " ") for l in range(depth)]))
circuitstr = "\n".join(circuitstr)

if return_str:
return circuitstr
else:
print(circuitstr)



def from_openqasm(self, openqasm : str):
"""
Initialize the circuit from openqasm text.
Args:
openqasm: input openqasm str.
"""
from numpy import pi
import re
self.openqasm = openqasm
# lines = self.openqasm.strip("\n").splitlines(";")
lines = self.openqasm.splitlines()
lines = [line for line in lines if line]
self.gates = []
self.measures = {}
measured_qubits = []
global_valid = True
for line in lines[2:]:
if line:
operations_qbs = line.split(" ", 1)
operations = operations_qbs[0]
if operations == "qreg":
qbs = operations_qbs[1]
self.num = int(re.findall("\d+", qbs)[0])
elif operations == "creg":
pass
elif operations == "measure":
qbs = operations_qbs[1]
indstr = re.findall("\d+", qbs)
inds = [int(indst) for indst in indstr]
mb = inds[0]
cb = inds[1]
self.measures[mb] = cb
measured_qubits.append(mb)
else:
qbs = operations_qbs[1]
indstr = re.findall("\d+", qbs)
inds = [int(indst) for indst in indstr]
valid = True
for pos in inds:
if pos in measured_qubits:
valid = False
global_valid = False
break

if valid:
if operations == "barrier":
self.barrier(inds)

else:
sp_op = operations.split("(")
gatename = sp_op[0]
if gatename == "delay":
paras = sp_op[1].strip("()")
duration = int(re.findall("\d+", paras)[0])
unit = re.findall("[a-z]+", paras)[0]
self.delay(inds[0], duration, unit)
elif gatename == "xy":
paras = sp_op[1].strip("()")
duration = int(re.findall("\d+", paras)[0])
unit = re.findall("[a-z]+", paras)[0]
self.xy(min(inds), max(inds), duration, unit)
else:
if len(sp_op) > 1:
paras = sp_op[1].strip("()")
parastr = paras.split(",")
paras = [eval(parai, {"pi": pi}) for parai in parastr]

if gatename == "cx":
self.cnot(inds[0], inds[1])
elif gatename == "cy":
self.cy(inds[0], inds[1])
elif gatename == "cz":
self.cz(inds[0], inds[1])
elif gatename == "cp":
self.cp(inds[0], inds[1], paras[0])
elif gatename == "swap":
self.swap(inds[0], inds[1])
elif gatename == "rx":
self.rx(inds[0], paras[0])
elif gatename == "ry":
self.ry(inds[0], paras[0])
elif gatename == "rz":
self.rz(inds[0], paras[0])
elif gatename == "p":
self.p(inds[0], paras[0])
elif gatename == "x":
self.x(inds[0])
elif gatename == "y":
self.y(inds[0])
elif gatename == "z":
self.z(inds[0])
elif gatename == "h":
self.h(inds[0])
elif gatename == "id":
self.id(inds[0])
elif gatename == "s":
self.s(inds[0])
elif gatename == "sdg":
self.sdg(inds[0])
elif gatename == "t":
self.t(inds[0])
elif gatename == "tdg":
self.tdg(inds[0])
elif gatename == "sx":
self.sx(inds[0])
elif gatename == "ccx":
self.toffoli(inds[0], inds[1], inds[2])
elif gatename == "cswap":
self.fredkin(inds[0], inds[1], inds[2])
elif gatename == "u1":
self.rz(inds[0], paras[0])
elif gatename == "u2":
self.rz(inds[0], paras[1])
self.ry(inds[0], pi / 2)
self.rz(inds[0], paras[0])
elif gatename == "u3":
self.rz(inds[0], paras[2])
self.ry(inds[0], paras[0])
self.rz(inds[0], paras[1])
elif gatename == "rxx":
self.rxx(inds[0], inds[1], paras[0])
elif gatename == "ryy":
self.ryy(inds[0], inds[1], paras[0])
elif gatename == "rzz":
self.rzz(inds[0], inds[1], paras[0])
else:
print(
"Warning: Operations %s may be not supported by QuantumCircuit class currently." % gatename)

if not self.measures:
self.measures = dict(zip(range(self.num), range(self.num)))
if not global_valid:
print("Warning: All operations after measurement will be removed for executing on experiment")


def to_openqasm(self) -> str:
"""
Convert the circuit to openqasm text.
Returns:
Returns:
openqasm text.
"""
qasm = "OPENQASM 2.0;\ninclude \"qelib1.inc\";\n"
Expand All @@ -200,7 +335,7 @@ def id(self, pos: int) -> "QuantumCircuit":
Args:
pos (int): qubit the gate act.
"""
"""
self.gates.append(IdGate(pos))
return self

Expand Down Expand Up @@ -253,7 +388,7 @@ def t(self, pos: int) -> "QuantumCircuit":
"""
self.gates.append(TGate(pos))
return self

def tdg(self, pos: int) -> "QuantumCircuit":
"""
Tdg gate. (Inverse of T gate)
Expand Down Expand Up @@ -312,7 +447,7 @@ def w(self, pos: int) -> "QuantumCircuit":
"""
self.gates.append(WGate(pos))
return self

def sw(self, pos: int) -> "QuantumCircuit":
"""
√W gate.
Expand All @@ -322,7 +457,7 @@ def sw(self, pos: int) -> "QuantumCircuit":
"""
self.gates.append(SWGate(pos))
return self

def rx(self, pos: int, para: float) -> "QuantumCircuit":
"""
Single qubit rotation Rx gate.
Expand All @@ -337,7 +472,7 @@ def rx(self, pos: int, para: float) -> "QuantumCircuit":
def ry(self, pos: int, para: float) -> "QuantumCircuit":
"""
Single qubit rotation Ry gate.
Args:
pos (int): qubit the gate act.
para (float): rotation angle
Expand All @@ -348,7 +483,7 @@ def ry(self, pos: int, para: float) -> "QuantumCircuit":
def rz(self, pos: int, para: float) -> "QuantumCircuit":
"""
Single qubit rotation Rz gate.
Args:
pos (int): qubit the gate act.
para (float): rotation angle
Expand All @@ -359,7 +494,7 @@ def rz(self, pos: int, para: float) -> "QuantumCircuit":
def p(self, pos: int, para: float) -> "QuantumCircuit":
"""
Phase gate
Args:
pos (int): qubit the gate act.
para (float): rotation angle
Expand All @@ -369,7 +504,7 @@ def p(self, pos: int, para: float) -> "QuantumCircuit":
def cnot(self, ctrl: int, tar: int) -> "QuantumCircuit":
"""
CNOT gate.
Args:
ctrl (int): control qubit.
tar (int): target qubit.
Expand All @@ -391,7 +526,7 @@ def cy(self, ctrl: int, tar: int) -> "QuantumCircuit":
def cz(self, ctrl: int, tar: int) -> "QuantumCircuit":
"""
Control-Z gate.
Args:
ctrl (int): control qubit.
tar (int): target qubit.
Expand All @@ -416,7 +551,7 @@ def ct(self, ctrl: int, tar: int) -> "QuantumCircuit":
ctrl (int): control qubit.
tar (int): target qubit.
"""

self.gates.append(CTGate(ctrl, tar))
return self

Expand All @@ -430,12 +565,12 @@ def cp(self, ctrl: int, tar: int, para) -> "QuantumCircuit":
"""
self.gates.append(CPGate(ctrl, tar, para))
return self


def swap(self, q1: int, q2: int) -> "QuantumCircuit":
"""
SWAP gate
Args:
q1 (int): qubit the gate act.
q2 (int): qubit the gate act.
Expand All @@ -454,11 +589,11 @@ def toffoli(self, ctrl1: int, ctrl2: int, targ: int) -> "QuantumCircuit":
"""
self.gates.append(ToffoliGate(ctrl1, ctrl2, targ))
return self

def fredkin(self, ctrl: int, targ1:int , targ2: int) -> "QuantumCircuit":
"""
Fredkin gate
Args:
ctrl (int): control qubit
targ1 (int): target qubit
Expand All @@ -470,7 +605,7 @@ def fredkin(self, ctrl: int, targ1:int , targ2: int) -> "QuantumCircuit":
def barrier(self, qlist: List[int]) -> "QuantumCircuit":
"""
Add barrier for qubits in qlist.
Args:
qlist (list[int]): A list contain the qubit need add barrier. When qlist contain at least two qubit, the barrier will be added from minimum qubit to maximum qubit. For example: barrier([0, 2]) create barrier for qubits 0, 1, 2. To create discrete barrier, using barrier([0]), barrier([2]).
"""
Expand All @@ -484,7 +619,7 @@ def delay(self, pos, duration, unit="ns") -> "QuantumCircuit":
Args:
pos (int): qubit need delay.
duration (int): duration of qubit delay, which represents integer times of unit.
unit (str): time unit for the duration. Can be "ns" and "us".
unit (str): time unit for the duration. Can be "ns" and "us".
"""
self.gates.append(Delay(pos, duration, unit=unit))
return self
Expand Down Expand Up @@ -512,7 +647,7 @@ def rxx(self, q1: int, q2: int, theta):
"""
self.gates.append(RXXGate(q1, q2, theta))

def ryy(self, q1: int, q2: int, theta):
"""
Rotation about 2-qubit YY axis.
Expand All @@ -534,7 +669,7 @@ def rzz(self, q1: int, q2: int, theta):
"""
self.gates.append(RZZGate(q1, q2, theta))

def mcx(self, ctrls: List[int], targ: int):
"""
Multi-controlled X gate.
Expand All @@ -543,7 +678,7 @@ def mcx(self, ctrls: List[int], targ: int):
targ: Target qubits.
"""
self.gates.append(MCXGate(ctrls, targ))

def mcy(self, ctrls: List[int], targ: int):
"""
Multi-controlled Y gate.
Expand All @@ -552,7 +687,7 @@ def mcy(self, ctrls: List[int], targ: int):
targ: Target qubits.
"""
self.gates.append(MCYGate(ctrls, targ))

def mcz(self, ctrls: List[int], targ: int):
"""
Multi-controlled Z gate.
Expand All @@ -561,12 +696,12 @@ def mcz(self, ctrls: List[int], targ: int):
targ: Target qubits.
"""
self.gates.append(MCZGate(ctrls, targ))


def measure(self, pos: List[int], cbits: List[int] = []) -> None:
"""
Measurement setting for experiment device.
Args:
pos: Qubits need measure.
cbits: Classical bits keeping the measure results.
Expand All @@ -590,4 +725,3 @@ def add_pulse(self,
pulse.set_pos(pos)
self.gates.append(pulse)
return self

Loading

0 comments on commit 93edf5b

Please sign in to comment.