qiskit/mapper/_mapping.py
def optimize_1q_gates(circuit):
    """Simplify runs of single qubit gates in the QX basis.

    Return a new circuit that has been optimized.
    """
    qx_basis = ["u1", "u2", "u3", "cx", "id"]
    dag_unroller = DagUnroller(circuit, DAGBackend(qx_basis))
    unrolled = dag_unroller.expand_gates()

    runs = unrolled.collect_runs(["u1", "u2", "u3", "id"])
    for run in runs:
        qname = 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]
            assert nd["condition"] is None, "internal error"
            assert len(nd["qargs"]) == 1, "internal error"
            assert nd["qargs"][0] == qname, "internal error"
            left_name = nd["name"]
            assert left_name in ["u1", "u2", "u3", "id"], "internal error"
            if left_name == "u1":
                left_parameters = (N(0), N(0), nd["params"][0])
            elif left_name == "u2":
                left_parameters = (sympy.pi / 2, nd["params"][0], nd["params"][1])
            elif left_name == "u3":
                left_parameters = tuple(nd["params"])
            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_params = []
        if right_name == "u1":
            new_params = [right_parameters[2]]
        if right_name == "u2":
            new_params = [right_parameters[1], right_parameters[2]]
        if right_name == "u3":
            new_params = list(right_parameters)

        nx.set_node_attributes(unrolled.multi_graph, name='name',
                               values={run[0]: right_name})
        # params is a list of sympy symbols
        nx.set_node_attributes(unrolled.multi_graph, name='params',
                               values={run[0]: new_params})
        # 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
Simplify runs of single qubit gates in the QX basis.

    Return a new circuit that has been optimized.
    
Simplify runs of single qubit gates in the QX basis.
Return a new circuit that has been optimized.
Simplify runs of single qubit gates in the QX basis . Return a new circuit that has been optimized .
def optimize_1q_gates(circuit):
    qx_basis = ["u1", "u2", "u3", "cx", "id"]
    dag_unroller = DagUnroller(circuit, DAGBackend(qx_basis))
    unrolled = dag_unroller.expand_gates()
    runs = unrolled.collect_runs(["u1", "u2", "u3", "id"])
    for run in runs:
        qname = unrolled.multi_graph.node[run[0]]["qargs"][0]
        right_name = "u1"
        right_parameters = (N(0), N(0), N(0))  
        for current_node in run:
            nd = unrolled.multi_graph.node[current_node]
            assert nd["condition"] is None, "internal error"
            assert len(nd["qargs"]) == 1, "internal error"
            assert nd["qargs"][0] == qname, "internal error"
            left_name = nd["name"]
            assert left_name in ["u1", "u2", "u3", "id"], "internal error"
            if left_name == "u1":
                left_parameters = (N(0), N(0), nd["params"][0])
            elif left_name == "u2":
                left_parameters = (sympy.pi / 2, nd["params"][0], nd["params"][1])
            elif left_name == "u3":
                left_parameters = tuple(nd["params"])
            else:
                left_name = "u1"  
                left_parameters = (N(0), N(0), N(0))
            name_tuple = (left_name, right_name)
            if name_tuple == ("u1", "u1"):
                right_parameters = (N(0), N(0), right_parameters[2] +
                                    left_parameters[2])
            elif name_tuple == ("u1", "u2"):
                right_parameters = (sympy.pi / 2, right_parameters[1] +
                                    left_parameters[2], right_parameters[2])
            elif name_tuple == ("u2", "u1"):
                right_name = "u2"
                right_parameters = (sympy.pi / 2, left_parameters[1],
                                    right_parameters[2] + left_parameters[2])
            elif name_tuple == ("u1", "u3"):
                right_parameters = (right_parameters[0], right_parameters[1] +
                                    left_parameters[2], right_parameters[2])
            elif name_tuple == ("u3", "u1"):
                right_name = "u3"
                right_parameters = (left_parameters[0], left_parameters[1],
                                    right_parameters[2] + left_parameters[2])
            elif name_tuple == ("u2", "u2"):
                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:
                right_name = "u3"
                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])
            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])
            if right_name == "u3":
                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))
                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))
            if right_name == "u1" and (right_parameters[2] % (2 * sympy.pi)).is_zero:
                right_name = "nop"
            right_parameters = tuple(map(sympy.simplify, list(right_parameters)))
        new_params = []
        if right_name == "u1":
            new_params = [right_parameters[2]]
        if right_name == "u2":
            new_params = [right_parameters[1], right_parameters[2]]
        if right_name == "u3":
            new_params = list(right_parameters)
        nx.set_node_attributes(unrolled.multi_graph, name='name',
                               values={run[0]: right_name})
        nx.set_node_attributes(unrolled.multi_graph, name='params',
                               values={run[0]: new_params})
        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 optimize_1q_gates ( circuit ) : qx_basis = [ "u1" , "u2" , "u3" , "cx" , "id" ] dag_unroller = DagUnroller ( circuit , DAGBackend ( qx_basis ) ) unrolled = dag_unroller . expand_gates ( ) runs = unrolled . collect_runs ( [ "u1" , "u2" , "u3" , "id" ] ) for run in runs : qname = unrolled . multi_graph . node [ run [ 0 ] ] [ "qargs" ] [ 0 ] right_name = "u1" right_parameters = ( N ( 0 ) , N ( 0 ) , N ( 0 ) ) for current_node in run : nd = unrolled . multi_graph . node [ current_node ] assert nd [ "condition" ] is None , "internal error" assert len ( nd [ "qargs" ] ) == 1 , "internal error" assert nd [ "qargs" ] [ 0 ] == qname , "internal error" left_name = nd [ "name" ] assert left_name in [ "u1" , "u2" , "u3" , "id" ] , "internal error" if left_name == "u1" : left_parameters = ( N ( 0 ) , N ( 0 ) , nd [ "params" ] [ 0 ] ) elif left_name == "u2" : left_parameters = ( sympy . pi / 2 , nd [ "params" ] [ 0 ] , nd [ "params" ] [ 1 ] ) elif left_name == "u3" : left_parameters = tuple ( nd [ "params" ] ) else : left_name = "u1" left_parameters = ( N ( 0 ) , N ( 0 ) , N ( 0 ) ) name_tuple = ( left_name , right_name ) if name_tuple == ( "u1" , "u1" ) : right_parameters = ( N ( 0 ) , N ( 0 ) , right_parameters [ 2 ] + left_parameters [ 2 ] ) elif name_tuple == ( "u1" , "u2" ) : right_parameters = ( sympy . pi / 2 , right_parameters [ 1 ] + left_parameters [ 2 ] , right_parameters [ 2 ] ) elif name_tuple == ( "u2" , "u1" ) : right_name = "u2" right_parameters = ( sympy . pi / 2 , left_parameters [ 1 ] , right_parameters [ 2 ] + left_parameters [ 2 ] ) elif name_tuple == ( "u1" , "u3" ) : right_parameters = ( right_parameters [ 0 ] , right_parameters [ 1 ] + left_parameters [ 2 ] , right_parameters [ 2 ] ) elif name_tuple == ( "u3" , "u1" ) : right_name = "u3" right_parameters = ( left_parameters [ 0 ] , left_parameters [ 1 ] , right_parameters [ 2 ] + left_parameters [ 2 ] ) elif name_tuple == ( "u2" , "u2" ) : 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 : right_name = "u3" 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 ] ) 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 ] ) if right_name == "u3" : 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 ) ) 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 ) ) if right_name == "u1" and ( right_parameters [ 2 ] % ( 2 * sympy . pi ) ) . is_zero : right_name = "nop" right_parameters = tuple ( map ( sympy . simplify , list ( right_parameters ) ) ) new_params = [ ] if right_name == "u1" : new_params = [ right_parameters [ 2 ] ] if right_name == "u2" : new_params = [ right_parameters [ 1 ] , right_parameters [ 2 ] ] if right_name == "u3" : new_params = list ( right_parameters ) nx . set_node_attributes ( unrolled . multi_graph , name = 'name' , values = { run [ 0 ] : right_name } ) nx . set_node_attributes ( unrolled . multi_graph , name = 'params' , values = { run [ 0 ] : new_params } ) for current_node in run [ 1 : ] : unrolled . _remove_op_node ( current_node ) if right_name == "nop" : unrolled . _remove_op_node ( run [ 0 ] ) return unrolled
Simplify runs of single qubit gates in the QX basis.
Simplify runs of single qubit gates in the QX basis .
"""Simplify runs of single qubit gates in the QX basis.

    Return a new circuit that has been optimized.
    """ # (theta, phi, lambda) # replace id with u1 # Compose gates # u1(lambda1) * u1(lambda2) = u1(lambda1 + lambda2) # u1(lambda1) * u2(phi2, lambda2) = u2(phi2 + lambda1, lambda2) # u2(phi1, lambda1) * u1(lambda2) = u2(phi1, lambda1 + lambda2) # u1(lambda1) * u3(theta2, phi2, lambda2) = #     u3(theta2, phi2 + lambda1, lambda2) # u3(theta1, phi1, lambda1) * u1(lambda2) = #     u3(theta1, phi1, lambda1 + lambda2) # 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) # 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. # Evaluate the symbolic expressions for efficiency # 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 # Y rotation is pi/2 or -pi/2 mod 2*pi, so the gate is a u2 # theta = pi/2 + 2*k*pi # theta = -pi/2 + 2*k*pi # u1 and lambda is 0 mod 2*pi so gate is nop (up to a global phase) # Simplify the symbolic parameters # Replace the data of the first node in the run # params is a list of sympy symbols # Delete the other nodes in the run
circuit