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))
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()))
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)
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)
def to_instruction(self): """Convert to a UnitaryGate instruction.""" from qiskit.extensions.unitary import UnitaryGate return UnitaryGate(self.data)
def to_instruction(self): """Convert to a UnitaryGate instruction.""" # pylint: disable=cyclic-import from qiskit.extensions.unitary import UnitaryGate return UnitaryGate(self.data)
def WGate(): return UnitaryGate( (XGate().to_matrix() + YGate().to_matrix()) / np.sqrt(2))
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))
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))
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)
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)