def _define(self): """ gate rccx a,b,c { u2(0,pi) c; u1(pi/4) c; cx b, c; u1(-pi/4) c; cx a, c; u1(pi/4) c; cx b, c; u1(-pi/4) c; u2(0,pi) c; } """ definition = [] q = QuantumRegister(3, 'q') rule = [ (U2Gate(0, pi), [q[2]], []), # H gate (U1Gate(pi / 4), [q[2]], []), # T gate (CnotGate(), [q[1], q[2]], []), (U1Gate(-pi / 4), [q[2]], []), # inverse T gate (CnotGate(), [q[0], q[2]], []), (U1Gate(pi / 4), [q[2]], []), (CnotGate(), [q[1], q[2]], []), (U1Gate(-pi / 4), [q[2]], []), # inverse T gate (U2Gate(0, pi), [q[2]], []), # H gate ] for inst in rule: definition.append(inst) self.definition = definition
def _define(self): """ gate rccx a,b,c { u2(0,pi) c; u1(pi/4) c; cx b, c; u1(-pi/4) c; cx a, c; u1(pi/4) c; cx b, c; u1(-pi/4) c; u2(0,pi) c; } """ definition = [] q = QuantumRegister(3, 'q') definition = [ (U2Gate(0, pi), [q[2]], []), # H gate (U1Gate(pi / 4), [q[2]], []), # T gate (CXGate(), [q[1], q[2]], []), (U1Gate(-pi / 4), [q[2]], []), # inverse T gate (CXGate(), [q[0], q[2]], []), (U1Gate(pi / 4), [q[2]], []), (CXGate(), [q[1], q[2]], []), (U1Gate(-pi / 4), [q[2]], []), # inverse T gate (U2Gate(0, pi), [q[2]], []), # H gate ] self.definition = definition
def simplify_U(theta, phi, lam): """Return the gate u1, u2, or u3 implementing U with the fewest pulses. The returned gate implements U exactly, not up to a global phase. Args: theta, phi, lam: input Euler rotation angles for a general U gate Returns: Gate: one of IdGate, U1Gate, U2Gate, U3Gate. """ gate = U3Gate(theta, phi, lam) # Y rotation is 0 mod 2*pi, so the gate is a u1 if abs(gate.params[0] % (2.0 * math.pi)) < _CUTOFF_PRECISION: gate = U1Gate(gate.params[0] + gate.params[1] + gate.params[2]) # Y rotation is pi/2 or -pi/2 mod 2*pi, so the gate is a u2 if isinstance(gate, U3Gate): # theta = pi/2 + 2*k*pi if abs((gate.params[0] - math.pi / 2) % (2.0 * math.pi)) < _CUTOFF_PRECISION: gate = U2Gate(gate.params[1], gate.params[2] + (gate.params[0] - math.pi / 2)) # theta = -pi/2 + 2*k*pi if abs((gate.params[0] + math.pi / 2) % (2.0 * math.pi)) < _CUTOFF_PRECISION: gate = U2Gate( gate.params[1] + math.pi, gate.params[2] - math.pi + (gate.params[0] + math.pi / 2)) # u1 and lambda is 0 mod 4*pi so gate is nop if isinstance(gate, U1Gate) and abs(gate.params[0] % (4.0 * math.pi)) < _CUTOFF_PRECISION: gate = IdGate() return gate
def _define(self): """ gate rcccx a,b,c,d { u2(0,pi) d; u1(pi/4) d; cx c,d; u1(-pi/4) d; u2(0,pi) d; cx a,d; u1(pi/4) d; cx b,d; u1(-pi/4) d; cx a,d; u1(pi/4) d; cx b,d; u1(-pi/4) d; u2(0,pi) d; u1(pi/4) d; cx c,d; u1(-pi/4) d; u2(0,pi) d; } """ definition = [] q = QuantumRegister(4, 'q') rule = [ (U2Gate(0, pi), [q[3]], []), # H gate (U1Gate(pi / 4), [q[3]], []), # T gate (CXGate(), [q[2], q[3]], []), (U1Gate(-pi / 4), [q[3]], []), # inverse T gate (U2Gate(0, pi), [q[3]], []), (CXGate(), [q[0], q[3]], []), (U1Gate(pi / 4), [q[3]], []), (CXGate(), [q[1], q[3]], []), (U1Gate(-pi / 4), [q[3]], []), (CXGate(), [q[0], q[3]], []), (U1Gate(pi / 4), [q[3]], []), (CXGate(), [q[1], q[3]], []), (U1Gate(-pi / 4), [q[3]], []), (U2Gate(0, pi), [q[3]], []), (U1Gate(pi / 4), [q[3]], []), (CXGate(), [q[2], q[3]], []), (U1Gate(-pi / 4), [q[3]], []), (U2Gate(0, pi), [q[3]], []), ] for inst in rule: definition.append(inst) self.definition = definition
def _define(self): """ gate rc3x a,b,c,d { u2(0,pi) d; u1(pi/4) d; cx c,d; u1(-pi/4) d; u2(0,pi) d; cx a,d; u1(pi/4) d; cx b,d; u1(-pi/4) d; cx a,d; u1(pi/4) d; cx b,d; u1(-pi/4) d; u2(0,pi) d; u1(pi/4) d; cx c,d; u1(-pi/4) d; u2(0,pi) d; } """ q = QuantumRegister(4, 'q') definition = [ (U2Gate(0, pi), [q[3]], []), # H gate (U1Gate(pi / 4), [q[3]], []), # T gate (CXGate(), [q[2], q[3]], []), (U1Gate(-pi / 4), [q[3]], []), # inverse T gate (U2Gate(0, pi), [q[3]], []), (CXGate(), [q[0], q[3]], []), (U1Gate(pi / 4), [q[3]], []), (CXGate(), [q[1], q[3]], []), (U1Gate(-pi / 4), [q[3]], []), (CXGate(), [q[0], q[3]], []), (U1Gate(pi / 4), [q[3]], []), (CXGate(), [q[1], q[3]], []), (U1Gate(-pi / 4), [q[3]], []), (U2Gate(0, pi), [q[3]], []), (U1Gate(pi / 4), [q[3]], []), (CXGate(), [q[2], q[3]], []), (U1Gate(-pi / 4), [q[3]], []), (U2Gate(0, pi), [q[3]], []), ] self.definition = definition
def _define(self): """ Decomposition into a single CR gate is ----X---| CR |------- ----H---|-theta|---H--- """ definition = [] q = QuantumRegister(2, "q") theta = self.params[0] rule = [ (DirectRXGate(pi), [q[0]], []), (U2Gate(0, pi), [q[1]], []), (CRGate(-theta), [q[0], q[1]], []), (U2Gate(0, pi), [q[1]], []), ] for inst in rule: definition.append(inst) self.definition = definition
def _define(self): """ gate h a { u2(0,pi) a; } """ definition = [] q = QuantumRegister(1, "q") rule = [(U2Gate(0, pi), [q[0]], [])] for inst in rule: definition.append(inst) self.definition = definition
def _define(self): """ gate h a { u2(0,pi) a; } """ from qiskit.extensions.standard.u2 import U2Gate definition = [] q = QuantumRegister(1, "q") rule = [(U2Gate(0, pi), [q[0]], [])] for inst in rule: definition.append(inst) self.definition = definition
def _define_decompositions(self): """ gate h a { u2(0,pi) a; } """ decomposition = DAGCircuit() q = QuantumRegister(1, "q") decomposition.add_qreg(q) rule = [U2Gate(0, pi, q[0])] for inst in rule: decomposition.apply_operation_back(inst) self._decompositions = [decomposition]
def _build_composite_gate(self, x, qr): composite_gate = CompositeGate( "first_order_expansion", [], [qr[i] for i in range(self._num_qubits)]) for _ in range(self._depth): for i in range(x.shape[0]): composite_gate._attach(U2Gate(0, np.pi, qr[i])) composite_gate._attach(U1Gate(2 * x[i], qr[i])) return composite_gate
def _define(self): """Calculate a subcircuit that implements this unitary.""" definition = [] q = QuantumRegister(2, "q") theta = self.params[0] rule = [ (U3Gate(np.pi / 2, theta, 0), [q[0]], []), (HGate(), [q[1]], []), (CnotGate(), [q[0], q[1]], []), (U1Gate(-theta), [q[1]], []), (CnotGate(), [q[0], q[1]], []), (HGate(), [q[1]], []), (U2Gate(-np.pi, np.pi - theta), [q[0]], []), ] for inst in rule: definition.append(inst) self.definition = definition
def _build_composite_gate(self, x, qr): composite_gate = CompositeGate( "second_order_expansion", [], [qr[i] for i in range(self._num_qubits)]) for _ in range(self._depth): for i in range(x.shape[0]): composite_gate._attach(U2Gate(0, np.pi, qr[i])) composite_gate._attach(U1Gate(2 * x[i], qr[i])) for src, targs in self._entangler_map.items(): for targ in targs: composite_gate._attach(CnotGate(qr[src], qr[targ])) composite_gate._attach( U1Gate(2 * (np.pi - x[src]) * (np.pi - x[targ]), qr[targ])) composite_gate._attach(CnotGate(qr[src], qr[targ])) return composite_gate
def _define(self): """Calculate a subcircuit that implements this unitary.""" from qiskit.extensions.standard.x import CnotGate from qiskit.extensions.standard.u1 import U1Gate from qiskit.extensions.standard.u2 import U2Gate from qiskit.extensions.standard.u3 import U3Gate from qiskit.extensions.standard.h import HGate definition = [] q = QuantumRegister(2, "q") theta = self.params[0] rule = [ (U3Gate(np.pi / 2, theta, 0), [q[0]], []), (HGate(), [q[1]], []), (CnotGate(), [q[0], q[1]], []), (U1Gate(-theta), [q[1]], []), (CnotGate(), [q[0], q[1]], []), (HGate(), [q[1]], []), (U2Gate(-np.pi, np.pi - theta), [q[0]], []), ] for inst in rule: definition.append(inst) self.definition = definition
def optimize_1q_gates(circuit): """Simplify runs of single qubit gates in the QX basis. Return a new circuit that has been optimized. """ from qiskit.transpiler.passes.mapping.unroller import Unroller qx_basis = ["u1", "u2", "u3", "cx", "id"] unrolled = Unroller(qx_basis).run(circuit) runs = unrolled.collect_runs(["u1", "u2", "u3", "id"]) for run in runs: run_qarg = unrolled.multi_graph.node[run[0]]["qargs"][0] right_name = "u1" right_parameters = (N(0), N(0), N(0)) # (theta, phi, lambda) for current_node in run: nd = unrolled.multi_graph.node[current_node] left_name = nd["name"] if (nd["condition"] is not None or len(nd["qargs"]) != 1 or nd["qargs"][0] != run_qarg or left_name not in ["u1", "u2", "u3", "id"]): raise MapperError("internal error") if left_name == "u1": left_parameters = (N(0), N(0), nd["op"].param[0]) elif left_name == "u2": left_parameters = (sympy.pi / 2, nd["op"].param[0], nd["op"].param[1]) elif left_name == "u3": left_parameters = tuple(nd["op"].param) else: left_name = "u1" # replace id with u1 left_parameters = (N(0), N(0), N(0)) # Compose gates name_tuple = (left_name, right_name) if name_tuple == ("u1", "u1"): # u1(lambda1) * u1(lambda2) = u1(lambda1 + lambda2) right_parameters = (N(0), N(0), right_parameters[2] + left_parameters[2]) elif name_tuple == ("u1", "u2"): # u1(lambda1) * u2(phi2, lambda2) = u2(phi2 + lambda1, lambda2) right_parameters = (sympy.pi / 2, right_parameters[1] + left_parameters[2], right_parameters[2]) elif name_tuple == ("u2", "u1"): # u2(phi1, lambda1) * u1(lambda2) = u2(phi1, lambda1 + lambda2) right_name = "u2" right_parameters = (sympy.pi / 2, left_parameters[1], right_parameters[2] + left_parameters[2]) elif name_tuple == ("u1", "u3"): # u1(lambda1) * u3(theta2, phi2, lambda2) = # u3(theta2, phi2 + lambda1, lambda2) right_parameters = (right_parameters[0], right_parameters[1] + left_parameters[2], right_parameters[2]) elif name_tuple == ("u3", "u1"): # u3(theta1, phi1, lambda1) * u1(lambda2) = # u3(theta1, phi1, lambda1 + lambda2) right_name = "u3" right_parameters = (left_parameters[0], left_parameters[1], right_parameters[2] + left_parameters[2]) elif name_tuple == ("u2", "u2"): # Using Ry(pi/2).Rz(2*lambda).Ry(pi/2) = # Rz(pi/2).Ry(pi-2*lambda).Rz(pi/2), # u2(phi1, lambda1) * u2(phi2, lambda2) = # u3(pi - lambda1 - phi2, phi1 + pi/2, lambda2 + pi/2) right_name = "u3" right_parameters = (sympy.pi - left_parameters[2] - right_parameters[1], left_parameters[1] + sympy.pi / 2, right_parameters[2] + sympy.pi / 2) elif name_tuple[1] == "nop": right_name = left_name right_parameters = left_parameters else: # For composing u3's or u2's with u3's, use # u2(phi, lambda) = u3(pi/2, phi, lambda) # together with the qiskit.mapper.compose_u3 method. right_name = "u3" # Evaluate the symbolic expressions for efficiency left_parameters = tuple( map(lambda x: x.evalf(), list(left_parameters))) right_parameters = tuple( map(lambda x: x.evalf(), list(right_parameters))) right_parameters = compose_u3(left_parameters[0], left_parameters[1], left_parameters[2], right_parameters[0], right_parameters[1], right_parameters[2]) # Why evalf()? This program: # OPENQASM 2.0; # include "qelib1.inc"; # qreg q[2]; # creg c[2]; # u3(0.518016983430947*pi,1.37051598592907*pi,1.36816383603222*pi) q[0]; # u3(1.69867232277986*pi,0.371448347747471*pi,0.461117217930936*pi) q[0]; # u3(0.294319836336836*pi,0.450325871124225*pi,1.46804720442555*pi) q[0]; # measure q -> c; # took >630 seconds (did not complete) to optimize without # calling evalf() at all, 19 seconds to optimize calling # evalf() AFTER compose_u3, and 1 second to optimize # calling evalf() BEFORE compose_u3. # 1. Here down, when we simplify, we add f(theta) to lambda to # correct the global phase when f(theta) is 2*pi. This isn't # necessary but the other steps preserve the global phase, so # we continue in that manner. # 2. The final step will remove Z rotations by 2*pi. # 3. Note that is_zero is true only if the expression is exactly # zero. If the input expressions have already been evaluated # then these final simplifications will not occur. # TODO After we refactor, we should have separate passes for # exact and approximate rewriting. # Y rotation is 0 mod 2*pi, so the gate is a u1 if (right_parameters[0] % (2 * sympy.pi)).is_zero \ and right_name != "u1": right_name = "u1" right_parameters = (0, 0, right_parameters[1] + right_parameters[2] + right_parameters[0]) # Y rotation is pi/2 or -pi/2 mod 2*pi, so the gate is a u2 if right_name == "u3": # theta = pi/2 + 2*k*pi if ((right_parameters[0] - sympy.pi / 2) % (2 * sympy.pi)).is_zero: right_name = "u2" right_parameters = (sympy.pi / 2, right_parameters[1], right_parameters[2] + (right_parameters[0] - sympy.pi / 2)) # theta = -pi/2 + 2*k*pi if ((right_parameters[0] + sympy.pi / 2) % (2 * sympy.pi)).is_zero: right_name = "u2" right_parameters = (sympy.pi / 2, right_parameters[1] + sympy.pi, right_parameters[2] - sympy.pi + (right_parameters[0] + sympy.pi / 2)) # u1 and lambda is 0 mod 2*pi so gate is nop (up to a global phase) if right_name == "u1" and (right_parameters[2] % (2 * sympy.pi)).is_zero: right_name = "nop" # Simplify the symbolic parameters right_parameters = tuple( map(sympy.simplify, list(right_parameters))) # Replace the data of the first node in the run new_op = Instruction("", [], [], []) if right_name == "u1": new_op = U1Gate(right_parameters[2], run_qarg) if right_name == "u2": new_op = U2Gate(right_parameters[1], right_parameters[2], run_qarg) if right_name == "u3": new_op = U3Gate(*right_parameters, run_qarg) nx.set_node_attributes(unrolled.multi_graph, name='name', values={run[0]: right_name}) nx.set_node_attributes(unrolled.multi_graph, name='op', values={run[0]: new_op}) # Delete the other nodes in the run for current_node in run[1:]: unrolled._remove_op_node(current_node) if right_name == "nop": unrolled._remove_op_node(run[0]) return unrolled
def run(self, dag): """Return a new circuit that has been optimized.""" runs = dag.collect_runs(["u1", "u2", "u3", "id"]) for run in runs: right_name = "u1" right_parameters = (0, 0, 0) # (theta, phi, lambda) for current_node in run: left_name = current_node.name if (current_node.condition is not None or len(current_node.qargs) != 1 or left_name not in ["u1", "u2", "u3", "id"]): raise MapperError("internal error") if left_name == "u1": left_parameters = (0, 0, current_node.op.params[0]) elif left_name == "u2": left_parameters = (np.pi / 2, current_node.op.params[0], current_node.op.params[1]) elif left_name == "u3": left_parameters = tuple(current_node.op.params) else: left_name = "u1" # replace id with u1 left_parameters = (0, 0, 0) # If there are any sympy objects coming from the gate convert # to numpy. left_parameters = tuple([float(x) for x in left_parameters]) # Compose gates name_tuple = (left_name, right_name) if name_tuple == ("u1", "u1"): # u1(lambda1) * u1(lambda2) = u1(lambda1 + lambda2) right_parameters = (0, 0, right_parameters[2] + left_parameters[2]) elif name_tuple == ("u1", "u2"): # u1(lambda1) * u2(phi2, lambda2) = u2(phi2 + lambda1, lambda2) right_parameters = (np.pi / 2, right_parameters[1] + left_parameters[2], right_parameters[2]) elif name_tuple == ("u2", "u1"): # u2(phi1, lambda1) * u1(lambda2) = u2(phi1, lambda1 + lambda2) right_name = "u2" right_parameters = (np.pi / 2, left_parameters[1], right_parameters[2] + left_parameters[2]) elif name_tuple == ("u1", "u3"): # u1(lambda1) * u3(theta2, phi2, lambda2) = # u3(theta2, phi2 + lambda1, lambda2) right_parameters = (right_parameters[0], right_parameters[1] + left_parameters[2], right_parameters[2]) elif name_tuple == ("u3", "u1"): # u3(theta1, phi1, lambda1) * u1(lambda2) = # u3(theta1, phi1, lambda1 + lambda2) right_name = "u3" right_parameters = (left_parameters[0], left_parameters[1], right_parameters[2] + left_parameters[2]) elif name_tuple == ("u2", "u2"): # Using Ry(pi/2).Rz(2*lambda).Ry(pi/2) = # Rz(pi/2).Ry(pi-2*lambda).Rz(pi/2), # u2(phi1, lambda1) * u2(phi2, lambda2) = # u3(pi - lambda1 - phi2, phi1 + pi/2, lambda2 + pi/2) right_name = "u3" right_parameters = (np.pi - left_parameters[2] - right_parameters[1], left_parameters[1] + np.pi / 2, right_parameters[2] + np.pi / 2) elif name_tuple[1] == "nop": right_name = left_name right_parameters = left_parameters else: # For composing u3's or u2's with u3's, use # u2(phi, lambda) = u3(pi/2, phi, lambda) # together with the qiskit.mapper.compose_u3 method. right_name = "u3" # Evaluate the symbolic expressions for efficiency right_parameters = Optimize1qGates.compose_u3( left_parameters[0], left_parameters[1], left_parameters[2], right_parameters[0], right_parameters[1], right_parameters[2]) # Why evalf()? This program: # OPENQASM 2.0; # include "qelib1.inc"; # qreg q[2]; # creg c[2]; # u3(0.518016983430947*pi,1.37051598592907*pi,1.36816383603222*pi) q[0]; # u3(1.69867232277986*pi,0.371448347747471*pi,0.461117217930936*pi) q[0]; # u3(0.294319836336836*pi,0.450325871124225*pi,1.46804720442555*pi) q[0]; # measure q -> c; # took >630 seconds (did not complete) to optimize without # calling evalf() at all, 19 seconds to optimize calling # evalf() AFTER compose_u3, and 1 second to optimize # calling evalf() BEFORE compose_u3. # 1. Here down, when we simplify, we add f(theta) to lambda to # correct the global phase when f(theta) is 2*pi. This isn't # necessary but the other steps preserve the global phase, so # we continue in that manner. # 2. The final step will remove Z rotations by 2*pi. # 3. Note that is_zero is true only if the expression is exactly # zero. If the input expressions have already been evaluated # then these final simplifications will not occur. # TODO After we refactor, we should have separate passes for # exact and approximate rewriting. # Y rotation is 0 mod 2*pi, so the gate is a u1 if np.mod(right_parameters[0], (2 * np.pi)) == 0 \ and right_name != "u1": right_name = "u1" right_parameters = (0, 0, right_parameters[1] + right_parameters[2] + right_parameters[0]) # Y rotation is pi/2 or -pi/2 mod 2*pi, so the gate is a u2 if right_name == "u3": # theta = pi/2 + 2*k*pi if np.mod((right_parameters[0] - np.pi / 2), (2 * np.pi)) == 0: right_name = "u2" right_parameters = (np.pi / 2, right_parameters[1], right_parameters[2] + (right_parameters[0] - np.pi / 2)) # theta = -pi/2 + 2*k*pi if np.mod((right_parameters[0] + np.pi / 2), (2 * np.pi)) == 0: right_name = "u2" right_parameters = (np.pi / 2, right_parameters[1] + np.pi, right_parameters[2] - np.pi + (right_parameters[0] + np.pi / 2)) # u1 and lambda is 0 mod 2*pi so gate is nop (up to a global phase) if right_name == "u1" and np.mod(right_parameters[2], (2 * np.pi)) == 0: right_name = "nop" # Replace the the first node in the run with a dummy DAG which contains a dummy # qubit. The name is irrelevant, because substitute_node_with_dag will take care of # putting it in the right place. run_qarg = (QuantumRegister(1, 'q'), 0) new_op = Gate(name="", num_qubits=1, params=[]) if right_name == "u1": new_op = U1Gate(right_parameters[2]) if right_name == "u2": new_op = U2Gate(right_parameters[1], right_parameters[2]) if right_name == "u3": new_op = U3Gate(*right_parameters) if right_name != 'nop': new_dag = DAGCircuit() new_dag.add_qreg(run_qarg[0]) new_dag.apply_operation_back(new_op, [run_qarg], []) dag.substitute_node_with_dag(run[0], new_dag) # Delete the other nodes in the run for current_node in run[1:]: dag.remove_op_node(current_node) if right_name == "nop": dag.remove_op_node(run[0]) return dag
def create_dag_op(self, name, args, qubits): """Create a DAG op node. """ if name == "u0": op = U0Gate(args[0], qubits[0]) elif name == "u1": op = U1Gate(args[0], qubits[0]) elif name == "u2": op = U2Gate(args[0], args[1], qubits[0]) elif name == "u3": op = U3Gate(args[0], args[1], args[2], qubits[0]) elif name == "x": op = XGate(qubits[0]) elif name == "y": op = YGate(qubits[0]) elif name == "z": op = ZGate(qubits[0]) elif name == "t": op = TGate(qubits[0]) elif name == "tdg": op = TdgGate(qubits[0]) elif name == "s": op = SGate(qubits[0]) elif name == "sdg": op = SdgGate(qubits[0]) elif name == "swap": op = SwapGate(qubits[0], qubits[1]) elif name == "rx": op = RXGate(args[0], qubits[0]) elif name == "ry": op = RYGate(args[0], qubits[0]) elif name == "rz": op = RZGate(args[0], qubits[0]) elif name == "rzz": op = RZZGate(args[0], qubits[0], qubits[1]) elif name == "id": op = IdGate(qubits[0]) elif name == "h": op = HGate(qubits[0]) elif name == "cx": op = CnotGate(qubits[0], qubits[1]) elif name == "cy": op = CyGate(qubits[0], qubits[1]) elif name == "cz": op = CzGate(qubits[0], qubits[1]) elif name == "ch": op = CHGate(qubits[0], qubits[1]) elif name == "crz": op = CrzGate(args[0], qubits[0], qubits[1]) elif name == "cu1": op = Cu1Gate(args[0], qubits[0], qubits[1]) elif name == "cu3": op = Cu3Gate(args[0], args[1], args[2], qubits[0], qubits[1]) elif name == "ccx": op = ToffoliGate(qubits[0], qubits[1], qubits[2]) elif name == "cswap": op = FredkinGate(qubits[0], qubits[1], qubits[2]) else: raise BackendError("unknown operation for name ast node name %s" % name) self.circuit.add_basis_element(op.name, len(op.qargs), len(op.cargs), len(op.param)) self.start_gate(op) self.end_gate(op)
def _define(self): """Define the MCX gate using a V-chain of CX gates.""" q = QuantumRegister(self.num_qubits, name='q') q_controls = q[:self.num_ctrl_qubits] q_target = q[self.num_ctrl_qubits] q_ancillas = q[self.num_ctrl_qubits + 1:] definition = [] if self._dirty_ancillas: i = self.num_ctrl_qubits - 3 ancilla_pre_rule = [ (U2Gate(0, numpy.pi), [q_target], []), (CXGate(), [q_target, q_ancillas[i]], []), (U1Gate(-numpy.pi / 4), [q_ancillas[i]], []), (CXGate(), [q_controls[-1], q_ancillas[i]], []), (U1Gate(numpy.pi / 4), [q_ancillas[i]], []), (CXGate(), [q_target, q_ancillas[i]], []), (U1Gate(-numpy.pi / 4), [q_ancillas[i]], []), (CXGate(), [q_controls[-1], q_ancillas[i]], []), (U1Gate(numpy.pi / 4), [q_ancillas[i]], []), ] for inst in ancilla_pre_rule: definition.append(inst) for j in reversed(range(2, self.num_ctrl_qubits - 1)): definition.append( (RCCXGate(), [q_controls[j], q_ancillas[i - 1], q_ancillas[i]], [])) i -= 1 definition.append( (RCCXGate(), [q_controls[0], q_controls[1], q_ancillas[0]], [])) i = 0 for j in range(2, self.num_ctrl_qubits - 1): definition.append( (RCCXGate(), [q_controls[j], q_ancillas[i], q_ancillas[i + 1]], [])) i += 1 if self._dirty_ancillas: ancilla_post_rule = [ (U1Gate(-numpy.pi / 4), [q_ancillas[i]], []), (CXGate(), [q_controls[-1], q_ancillas[i]], []), (U1Gate(numpy.pi / 4), [q_ancillas[i]], []), (CXGate(), [q_target, q_ancillas[i]], []), (U1Gate(-numpy.pi / 4), [q_ancillas[i]], []), (CXGate(), [q_controls[-1], q_ancillas[i]], []), (U1Gate(numpy.pi / 4), [q_ancillas[i]], []), (CXGate(), [q_target, q_ancillas[i]], []), (U2Gate(0, numpy.pi), [q_target], []), ] for inst in ancilla_post_rule: definition.append(inst) else: definition.append( (CCXGate(), [q_controls[-1], q_ancillas[i], q_target], [])) for j in reversed(range(2, self.num_ctrl_qubits - 1)): definition.append( (RCCXGate(), [q_controls[j], q_ancillas[i - 1], q_ancillas[i]], [])) i -= 1 definition.append( (RCCXGate(), [q_controls[0], q_controls[1], q_ancillas[i]], [])) if self._dirty_ancillas: for i, j in enumerate(list(range(2, self.num_ctrl_qubits - 1))): definition.append( (RCCXGate(), [q_controls[j], q_ancillas[i], q_ancillas[i + 1]], [])) self.definition = definition