Exemplo n.º 1
0
 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
Exemplo n.º 2
0
 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
Exemplo n.º 3
0
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
Exemplo n.º 4
0
    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
Exemplo n.º 5
0
    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
Exemplo n.º 6
0
    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
Exemplo n.º 7
0
 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
Exemplo n.º 8
0
 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
Exemplo n.º 9
0
 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]
Exemplo n.º 10
0
    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
Exemplo n.º 11
0
 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
Exemplo n.º 12
0
    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
Exemplo n.º 13
0
 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
Exemplo n.º 14
0
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
Exemplo n.º 15
0
    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
Exemplo n.º 16
0
    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)
Exemplo n.º 17
0
    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