예제 #1
0
 def test_conjugate(self):
     """test conjugate"""
     ymat = numpy.array([[0, -1j], [1j, 0]])
     uni = UnitaryGate([[0, 1j], [-1j, 0]])
     self.assertTrue(numpy.array_equal(uni.conjugate().to_matrix(), ymat))
예제 #2
0
 def test_adjoint(self):
     """test adjoint operation"""
     uni = UnitaryGate([[0, 1j], [-1j, 0]])
     self.assertTrue(
         numpy.array_equal(uni.adjoint().to_matrix(), uni.to_matrix()))
예제 #3
0
 def test_unitary_decomposition_via_definition(self):
     """Test decomposition for 1Q unitary via definition."""
     mat = numpy.array([[0, 1], [1, 0]])
     numpy.allclose(Operator(UnitaryGate(mat).definition).data, mat)
예제 #4
0
 def test_set_init_with_unitary(self):
     """test instantiation of new unitary with another one (copy)"""
     uni1 = UnitaryGate([[0, 1], [1, 0]])
     uni2 = UnitaryGate(uni1)
     self.assertEqual(uni1, uni2)
     self.assertFalse(uni1 is uni2)
예제 #5
0
 def to_instruction(self):
     """Convert to a UnitaryGate instruction."""
     from qiskit.extensions.unitary import UnitaryGate
     return UnitaryGate(self.data)
예제 #6
0
 def to_instruction(self):
     """Convert to a UnitaryGate instruction."""
     # pylint: disable=cyclic-import
     from qiskit.extensions.unitary import UnitaryGate
     return UnitaryGate(self.data)
예제 #7
0
def WGate():
    return UnitaryGate(
        (XGate().to_matrix() + YGate().to_matrix()) / np.sqrt(2))
예제 #8
0
 def test_unitary_control(self):
     """Test parameters of controlled - unitary."""
     mat = numpy.array([[0, 1], [1, 0]])
     gate = UnitaryGate(mat).control()
     self.assertTrue(numpy.allclose(gate.params, mat))
     self.assertTrue(numpy.allclose(gate.base_gate.params, mat))
예제 #9
0
 def test_unitary_decomposition_via_definition_2q(self):
     """Test decomposition for 2Q unitary via definition."""
     mat = numpy.array([[0, 0, 1, 0], [0, 0, 0, -1], [1, 0, 0, 0],
                        [0, -1, 0, 0]])
     self.assertTrue(
         numpy.allclose(Operator(UnitaryGate(mat).definition).data, mat))
예제 #10
0
    def test_gray_synth(self):
        """Test synthesis of a small parity network via gray_synth.

        The algorithm should take the following matrix as an input:
        S =
        [[0, 1, 1, 0, 1, 1],
         [0, 1, 1, 0, 1, 0],
         [0, 0, 0, 1, 1, 0],
         [1, 0, 0, 1, 1, 1],
         [0, 1, 0, 0, 1, 0],
         [0, 1, 0, 0, 1, 0]]

        Along with some rotation angles:
        ['s', 't', 'z', 's', 't', 't'])

        which together specify the Fourier expansion in the sum-over-paths representation
        of a quantum circuit.

        And should return the following circuit (or an equivalent one):
                          ┌───┐┌───┐┌───┐┌───┐┌───┐┌───┐┌───┐┌───┐┌───┐┌───┐┌───┐┌───┐┌───┐┌───┐
        q_0: |0>──────────┤ X ├┤ X ├┤ T ├┤ X ├┤ X ├┤ X ├┤ X ├┤ T ├┤ X ├┤ T ├┤ X ├┤ X ├┤ Z ├┤ X ├
                          └─┬─┘└─┬─┘└───┘└─┬─┘└─┬─┘└─┬─┘└─┬─┘└───┘└─┬─┘└───┘└─┬─┘└─┬─┘└───┘└─┬─┘
        q_1: |0>────────────┼────┼─────────■────┼────┼────┼─────────┼─────────┼────┼─────────■──
                            │    │              │    │    │         │         │    │
        q_2: |0>───────■────■────┼──────────────■────┼────┼─────────┼────■────┼────┼────────────
                ┌───┐┌─┴─┐┌───┐  │                   │    │         │  ┌─┴─┐  │    │
        q_3: |0>┤ S ├┤ X ├┤ S ├──■───────────────────┼────┼─────────■──┤ X ├──┼────┼────────────
                └───┘└───┘└───┘                      │    │            └───┘  │    │
        q_4: |0>─────────────────────────────────────■────┼───────────────────■────┼────────────
                                                          │                        │
        q_5: |0>──────────────────────────────────────────■────────────────────────■────────────

        """
        cnots = [[0, 1, 1, 0, 1, 1], [0, 1, 1, 0, 1, 0], [0, 0, 0, 1, 1, 0],
                 [1, 0, 0, 1, 1, 1], [0, 1, 0, 0, 1, 0], [0, 1, 0, 0, 1, 0]]
        angles = ['s', 't', 'z', 's', 't', 't']
        c_gray = graysynth(cnots, angles)
        unitary_gray = UnitaryGate(Operator(c_gray))

        # Create the circuit displayed above:
        q = QuantumRegister(6, 'q')
        c_compare = QuantumCircuit(q)
        c_compare.s(q[3])
        c_compare.cx(q[2], q[3])
        c_compare.s(q[3])
        c_compare.cx(q[2], q[0])
        c_compare.cx(q[3], q[0])
        c_compare.t(q[0])
        c_compare.cx(q[1], q[0])
        c_compare.cx(q[2], q[0])
        c_compare.cx(q[4], q[0])
        c_compare.cx(q[5], q[0])
        c_compare.t(q[0])
        c_compare.cx(q[3], q[0])
        c_compare.t(q[0])
        c_compare.cx(q[2], q[3])
        c_compare.cx(q[4], q[0])
        c_compare.cx(q[5], q[0])
        c_compare.z(q[0])
        c_compare.cx(q[1], q[0])
        unitary_compare = UnitaryGate(Operator(c_compare))

        # Check if the two circuits are equivalent
        self.assertEqual(unitary_gray, unitary_compare)
예제 #11
0
def append_tk_command_to_qiskit(
    op: "Op",
    args: List["UnitID"],
    qcirc: QuantumCircuit,
    qregmap: Dict[str, QuantumRegister],
    cregmap: Dict[str, ClassicalRegister],
    symb_map: Dict[Parameter, sympy.Symbol],
    range_preds: Dict[Bit, Tuple[List["UnitID"], int]],
) -> Instruction:
    optype = op.type
    if optype == OpType.Measure:
        qubit = args[0]
        bit = args[1]
        qb = qregmap[qubit.reg_name][qubit.index[0]]
        b = cregmap[bit.reg_name][bit.index[0]]
        return qcirc.measure(qb, b)

    if optype == OpType.Reset:
        qb = qregmap[args[0].reg_name][args[0].index[0]]
        return qcirc.reset(qb)

    if optype in [
            OpType.CircBox, OpType.ExpBox, OpType.PauliExpBox, OpType.Custom
    ]:
        subcircuit = op.get_circuit()
        subqc = tk_to_qiskit(subcircuit)
        qargs = []
        cargs = []
        for a in args:
            if a.type == UnitType.qubit:
                qargs.append(qregmap[a.reg_name][a.index[0]])
            else:
                cargs.append(cregmap[a.reg_name][a.index[0]])
        if optype == OpType.Custom:
            instruc = subqc.to_gate()
            instruc.name = op.get_name()
        else:
            instruc = subqc.to_instruction()
        return qcirc.append(instruc, qargs, cargs)
    if optype == OpType.Unitary2qBox:
        qargs = [qregmap[q.reg_name][q.index[0]] for q in args]
        u = op.get_matrix()
        g = UnitaryGate(u, label="u2q")
        return qcirc.append(g, qargs=qargs)
    if optype == OpType.Barrier:
        qargs = [qregmap[q.reg_name][q.index[0]] for q in args]
        g = Barrier(len(args))
        return qcirc.append(g, qargs=qargs)
    if optype == OpType.RangePredicate:
        if op.lower != op.upper:
            raise NotImplementedError
        range_preds[args[-1]] = (args[:-1], op.lower)
        # attach predicate to bit,
        # subsequent conditional will handle it
        return Instruction("", 0, 0, [])
    if optype == OpType.ConditionalGate:
        if args[0] in range_preds:
            assert op.value == 1
            condition_bits, value = range_preds[args[0]]
            del range_preds[args[0]]
            args = condition_bits + args[1:]
            width = len(condition_bits)
        else:
            width = op.width
            value = op.value
        regname = args[0].reg_name
        if len(cregmap[regname]) != width:
            raise NotImplementedError(
                "OpenQASM conditions must be an entire register")
        for i, a in enumerate(args[:width]):
            if a.reg_name != regname:
                raise NotImplementedError(
                    "OpenQASM conditions can only use a single register")
            if a.index != [i]:
                raise NotImplementedError(
                    "OpenQASM conditions must be an entire register in order")
        instruction = append_tk_command_to_qiskit(op.op, args[width:], qcirc,
                                                  qregmap, cregmap, symb_map,
                                                  range_preds)

        instruction.c_if(cregmap[regname], value)
        return instruction
    # normal gates
    qargs = [qregmap[q.reg_name][q.index[0]] for q in args]
    if optype == OpType.CnX:
        return qcirc.mcx(qargs[:-1], qargs[-1])

    # special case
    if optype == OpType.CnRy:
        # might as well do a bit more checking
        assert len(op.params) == 1
        alpha = param_to_qiskit(op.params[0], symb_map)
        assert len(qargs) >= 2
        if len(qargs) == 2:
            # presumably more efficient; single control only
            new_gate = CRYGate(alpha)
        else:
            new_ry_gate = RYGate(alpha)
            new_gate = MCMT(gate=new_ry_gate,
                            num_ctrl_qubits=len(qargs) - 1,
                            num_target_qubits=1)
        qcirc.append(new_gate, qargs)
        return qcirc

    # others are direct translations
    try:
        gatetype = _known_qiskit_gate_rev[optype]
    except KeyError as error:
        raise NotImplementedError("Cannot convert tket Op to Qiskit gate: " +
                                  op.get_name()) from error
    params = [param_to_qiskit(p, symb_map) for p in op.params]
    g = gatetype(*params)
    return qcirc.append(g, qargs=qargs)