def duplicate_instruction(inst): """Create a fresh instruction from an input instruction.""" if issubclass(inst.__class__, Instruction) and inst.__class__ not in [ Instruction, Gate]: if inst.name == 'barrier': new_inst = inst.__class__(inst.num_qubits) elif inst.name == 'initialize': params = getattr(inst, 'params', []) new_inst = inst.__class__(params) elif inst.name == 'snapshot': label = inst.params[0] snap_type = inst.params[1] new_inst = inst.__class__(inst.num_qubits, inst.num_clbits, label, snap_type) else: params = getattr(inst, 'params', []) new_inst = inst.__class__(*params) else: if isinstance(inst, Gate): new_inst = Gate(inst.name, inst.num_qubits, inst.params) else: new_inst = Instruction(name=inst.name, num_qubits=inst.num_qubits, num_clbits=inst.num_clbits, params=inst.params) new_inst.definition = inst.definition return new_inst
def apply(self, operation, wires, par): # type: (Any, Sequence[int], List) -> None """Apply a quantum operation. Args: operation (str): name of the operation wires (Sequence[int]): subsystems the operation is applied on par (tuple): parameters for the operation """ mapped_operation = self._operation_map[operation] if isinstance(mapped_operation, BasisState) and not self._first_operation: raise DeviceError("Operation {} cannot be used after other Operations have already been applied " "on a {} device.".format(operation, self.short_name)) self._first_operation = False qregs = [(self._reg, i) for i in wires] if isinstance(mapped_operation, str): dag = circuit_to_dag(QuantumCircuit(self._reg, self._creg, name='')) instruction = Instruction(mapped_operation, par, qregs, [], circuit=self._circuit) dag.apply_operation_back(instruction) qc = dag_to_circuit(dag) self._circuit = self._circuit + qc elif isinstance(mapped_operation, QiskitInstructions): op = mapped_operation # type: QiskitInstructions op.apply(qregs=qregs, param=list(par), circuit=self._circuit) else: raise ValueError("The operation is not of an expected type. This is a software bug!")
def readout_error_circuits(): """Readout error test circuits""" circuits = [] # Test circuit: ideal bell state for 1-qubit readout errors qr = QuantumRegister(2, 'qr') cr = ClassicalRegister(2, 'cr') circuit = QuantumCircuit(qr, cr) circuit.h(qr[0]) circuit.cx(qr[0], qr[1]) # Ensure qubit 0 is measured before qubit 1 circuit.barrier(qr) circuit.measure(qr[0], cr[0]) circuit.barrier(qr) circuit.measure(qr[1], cr[1]) # Add three copies of circuit circuits += 3 * [circuit] # 2-qubit correlated readout error circuit measure2 = Instruction("measure", 2, 2, []) # 2-qubit measure qr = QuantumRegister(2, 'qr') cr = ClassicalRegister(2, 'cr') circuit = QuantumCircuit(qr, cr) circuit.h(qr) circuit.barrier(qr) circuit.append(measure2, [0, 1], [0, 1]) circuits.append(circuit) return circuits
def _generate_cqasm_from_instructions(instructions, number_of_qubits=2, full_state_projection=True): experiment_dict = { 'instructions': instructions, 'header': { 'n_qubits': number_of_qubits, 'number_of_clbits': number_of_qubits, 'compiled_circuit_qasm': '' }, 'config': { 'coupling_map': 'all-to-all', 'basis_gates': 'x,y,z,h,rx,ry,rz,s,cx,ccx,u1,u2,u3,id,snapshot', 'n_qubits': number_of_qubits } } experiment = qiskit.qobj.QasmQobjExperiment.from_dict(experiment_dict) for instruction in experiment.instructions: if hasattr(instruction, 'params'): # convert params to params used in qiskit instructions qiskit_instruction = Instruction('dummy', 0, 0, instruction.params) instruction.params = qiskit_instruction.params simulator = QuantumInspireBackend(Mock(), Mock()) result = simulator._generate_cqasm(experiment, full_state_projection) return result
def test_opaque_instruction(self): """test opaque instruction does not decompose""" q = QuantumRegister(4) c = ClassicalRegister(2) circ = QuantumCircuit(q, c) opaque_inst = Instruction(name="my_inst", num_qubits=3, num_clbits=1, params=[0.5]) circ.append(opaque_inst, [q[3], q[1], q[0]], [c[1]]) self.assertEqual(circ.data[0][0].name, "my_inst") self.assertEqual(circ.decompose(), circ)
def test_opaque_instruction(self): """test opaque instruction""" inst = Instruction('opaque', 3, 0, []) gate = instruction_to_gate(inst) self.assertIsInstance(gate, Gate) inst_attr = inst.__dict__ gate_attr = gate.__dict__ for att, value in inst_attr.items(): with self.subTest(name=att): self.assertEqual(value, getattr(gate, att)) self.assertEqual(set(gate_attr.keys()) - set(inst_attr.keys()), {'_label'})
def test_append_rejects_wrong_types(self, specifier): """Test that various bad inputs are rejected, both given loose or in sublists.""" test = QuantumCircuit(2, 2) # Use a default Instruction to be sure that there's not overridden broadcasting. opaque = Instruction("opaque", 1, 1, []) with self.subTest("q"), self.assertRaisesRegex(CircuitError, "Invalid bit index"): test.append(opaque, [specifier], [0]) with self.subTest("c"), self.assertRaisesRegex(CircuitError, "Invalid bit index"): test.append(opaque, [0], [specifier]) with self.subTest("q list"), self.assertRaisesRegex(CircuitError, "Invalid bit index"): test.append(opaque, [[specifier]], [[0]]) with self.subTest("c list"), self.assertRaisesRegex(CircuitError, "Invalid bit index"): test.append(opaque, [[0]], [[specifier]])
def test_qobj_to_circuits_with_opaque(self): """Check qobj_to_circuit's result with an opaque instruction.""" opaque_inst = Instruction(name='my_inst', num_qubits=4, num_clbits=2, params=[0.5, 0.4]) q = QuantumRegister(6, name='q') c = ClassicalRegister(4, name='c') circ = QuantumCircuit(q, c, name='circ') circ.append(opaque_inst, [q[0], q[2], q[5], q[3]], [c[3], c[0]]) dag = circuit_to_dag(circ) qobj = assemble(circ) out_circuit = qobj_to_circuits(qobj)[0] self.assertEqual(circuit_to_dag(out_circuit), dag)
def test_assemble_opaque_inst(self): """Test opaque instruction is assembled as-is""" opaque_inst = Instruction(name='my_inst', num_qubits=4, num_clbits=2, params=[0.5, 0.4]) q = QuantumRegister(6, name='q') c = ClassicalRegister(4, name='c') circ = QuantumCircuit(q, c, name='circ') circ.append(opaque_inst, [q[0], q[2], q[5], q[3]], [c[3], c[0]]) qobj = assemble(circ) self.assertIsInstance(qobj, QasmQobj) self.assertEqual(len(qobj.experiments[0].instructions), 1) self.assertEqual(qobj.experiments[0].instructions[0].name, 'my_inst') self.assertEqual(qobj.experiments[0].instructions[0].qubits, [0, 2, 5, 3]) self.assertEqual(qobj.experiments[0].instructions[0].memory, [3, 0]) self.assertEqual(qobj.experiments[0].instructions[0].params, [0.5, 0.4])
def test_instructions_soft_compare(self): """Test soft comparison between instructions.""" theta = Parameter('theta') phi = Parameter('phi') # Verify that we are insensitive when there are parameters. self.assertTrue(Instruction('u', 1, 0, [0.3, phi, 0.4]).soft_compare( Instruction('u', 1, 0, [theta, phi, 0.4]))) # Verify that normal equality still holds. self.assertTrue(Instruction('u', 1, 0, [0.4, 0.5]).soft_compare( Instruction('u', 1, 0, [0.4, 0.5]))) # Test that when names differ we get False. self.assertFalse(Instruction('u', 1, 0, [0.4, phi]).soft_compare( Instruction('v', 1, 0, [theta, phi]))) # Test cutoff precision. self.assertFalse(Instruction('v', 1, 0, [0.401, phi]).soft_compare( Instruction('v', 1, 0, [0.4, phi]))) # Test cutoff precision. self.assertTrue(Instruction('v', 1, 0, [0.4+1.0e-20, phi]).soft_compare( Instruction('v', 1, 0, [0.4, phi])))
def test_opaque_instruction(self): """Test the disassembler handles opaque instructions correctly.""" opaque_inst = Instruction(name="my_inst", num_qubits=4, num_clbits=2, params=[0.5, 0.4]) q = QuantumRegister(6, name="q") c = ClassicalRegister(4, name="c") circ = QuantumCircuit(q, c, name="circ") circ.append(opaque_inst, [q[0], q[2], q[5], q[3]], [c[3], c[0]]) qobj = assemble(circ) circuits, run_config_out, header = disassemble(qobj) run_config_out = RunConfig(**run_config_out) self.assertEqual(run_config_out.n_qubits, 6) self.assertEqual(run_config_out.memory_slots, 4) self.assertEqual(len(circuits), 1) self.assertEqual(circuits[0], circ) self.assertEqual({}, header)
def test_repr_of_instructions(self): """Test the __repr__ method of the Instruction class""" ins1 = Instruction("test_instruction", 3, 5, [0, 1, 2, 3]) self.assertEqual( repr(ins1), "Instruction(name='{}', num_qubits={}, num_clbits={}, params={})". format(ins1.name, ins1.num_qubits, ins1.num_clbits, ins1.params), ) ins2 = random_circuit(num_qubits=4, depth=4, measure=True).to_instruction() self.assertEqual( repr(ins2), "Instruction(name='{}', num_qubits={}, num_clbits={}, params={})". format(ins2.name, ins2.num_qubits, ins2.num_clbits, ins2.params), )
def test_instructions_equal_with_parameters(self): """Test equality of instructions for cases with Parameters.""" theta = Parameter('theta') phi = Parameter('phi') # Verify we can check params including parameters self.assertEqual(Instruction('u', 1, 0, [theta, phi, 0.4]), Instruction('u', 1, 0, [theta, phi, 0.4])) # Verify we can test for correct parameter order self.assertNotEqual(Instruction('u', 1, 0, [theta, phi, 0]), Instruction('u', 1, 0, [phi, theta, 0])) # Verify we can still find a wrong fixed param if we use parameters self.assertNotEqual(Instruction('u', 1, 0, [theta, phi, 0.4]), Instruction('u', 1, 0, [theta, phi, 0.5])) # Verify we can find cases when param != float self.assertNotEqual(Instruction('u', 1, 0, [0.3, phi, 0.4]), Instruction('u', 1, 0, [theta, phi, 0.5]))
def test_instructions_equal(self): """Test equality of two instructions.""" hop1 = Instruction('h', 1, 0, []) hop2 = Instruction('s', 1, 0, []) hop3 = Instruction('h', 1, 0, []) uop1 = Instruction('u', 1, 0, [0.4, 0.5, 0.5]) uop2 = Instruction('u', 1, 0, [0.4, 0.6, 0.5]) uop3 = Instruction('v', 1, 0, [0.4, 0.5, 0.5]) uop4 = Instruction('u', 1, 0, [0.4, 0.5, 0.5]) self.assertFalse(hop1 == hop2) self.assertTrue(hop1 == hop3) self.assertFalse(uop1 == uop2) self.assertTrue(uop1 == uop4) self.assertFalse(uop1 == uop3) self.assertTrue(HGate() == HGate()) self.assertFalse(HGate() == CnotGate()) self.assertFalse(hop1 == HGate())
def test_instructions_equal_with_parameter_expressions(self): """Test equality of instructions for cases with ParameterExpressions.""" theta = Parameter("theta") phi = Parameter("phi") sum_ = theta + phi product_ = theta * phi # Verify we can check params including parameters self.assertEqual( Instruction("u", 1, 0, [sum_, product_, 0.4]), Instruction("u", 1, 0, [sum_, product_, 0.4]), ) # Verify we can test for correct parameter order self.assertNotEqual(Instruction("u", 1, 0, [product_, sum_, 0]), Instruction("u", 1, 0, [sum_, product_, 0])) # Verify we can still find a wrong fixed param if we use parameters self.assertNotEqual(Instruction("u", 1, 0, [sum_, phi, 0.4]), Instruction("u", 1, 0, [sum_, phi, 0.5])) # Verify we can find cases when param != float self.assertNotEqual(Instruction("u", 1, 0, [0.3, sum_, 0.4]), Instruction("u", 1, 0, [product_, sum_, 0.5]))
def test_instructions_equal(self): """Test equality of two instructions. """ qr = QuantumRegister(3) cr = ClassicalRegister(3) hop1 = Instruction('h', [], qr, cr) hop2 = Instruction('s', [], qr, cr) hop3 = Instruction('h', [], qr, cr) uop1 = Instruction('u', [0.4, 0.5, 0.5], qr, cr) uop2 = Instruction('u', [0.4, 0.6, 0.5], qr, cr) uop3 = Instruction('v', [0.4, 0.5, 0.5], qr, cr) uop4 = Instruction('u', [0.4, 0.5, 0.5], qr, cr) self.assertFalse(hop1 == hop2) self.assertTrue(hop1 == hop3) self.assertFalse(uop1 == uop2) self.assertTrue(uop1 == uop4) self.assertFalse(uop1 == uop3) self.assertTrue(HGate(qr[0]) == HGate(qr[1])) self.assertFalse(HGate(qr[0]) == CnotGate(qr[0], qr[1])) self.assertFalse(hop1 == HGate(qr[2]))
def test_instructions_equal(self): """Test equality of two instructions.""" hop1 = Instruction('h', 1, 0, []) hop2 = Instruction('s', 1, 0, []) hop3 = Instruction('h', 1, 0, []) self.assertFalse(hop1 == hop2) self.assertTrue(hop1 == hop3) uop1 = Instruction('u', 1, 0, [0.4, 0.5, 0.5]) uop2 = Instruction('u', 1, 0, [0.4, 0.6, 0.5]) uop3 = Instruction('v', 1, 0, [0.4, 0.5, 0.5]) uop4 = Instruction('u', 1, 0, [0.4, 0.5, 0.5]) self.assertFalse(uop1 == uop2) self.assertTrue(uop1 == uop4) self.assertFalse(uop1 == uop3) self.assertTrue(HGate() == HGate()) self.assertFalse(HGate() == CnotGate()) self.assertFalse(hop1 == HGate()) eop1 = Instruction('kraus', 1, 0, [np.array([[1, 0], [0, 1]])]) eop2 = Instruction('kraus', 1, 0, [np.array([[0, 1], [1, 0]])]) eop3 = Instruction('kraus', 1, 0, [np.array([[1, 0], [0, 1]])]) eop4 = Instruction('kraus', 1, 0, [np.eye(4)]) self.assertTrue(eop1 == eop3) self.assertFalse(eop1 == eop2) self.assertFalse(eop1 == eop4)
def to_instruction(self): """Convert the ReadoutError to a circuit Instruction.""" return Instruction("roerror", 0, self.number_of_qubits, self._probabilities)
def _to_circuit(cls, op): if isinstance(op, QuantumCircuit): return op if isinstance(op, tuple): inst, qubits = op circ = QuantumCircuit(max(qubits) + 1) circ.append(inst, qargs=qubits) return circ if isinstance(op, Instruction): if op.num_clbits > 0: raise NoiseError( f"Unable to convert instruction with clbits: {op.__class__.__name__}" ) circ = QuantumCircuit(op.num_qubits) circ.append(op, qargs=list(range(op.num_qubits))) return circ if isinstance(op, QuantumChannel): if not op.is_cptp(atol=cls.atol): raise NoiseError("Input quantum channel is not CPTP.") try: return cls._to_circuit(Kraus(op).to_instruction()) except QiskitError as err: raise NoiseError( f"Fail to convert {op.__class__.__name__} to Instruction." ) from err if isinstance(op, BaseOperator): if hasattr(op, 'to_instruction'): try: return cls._to_circuit(op.to_instruction()) except QiskitError as err: raise NoiseError( f"Fail to convert {op.__class__.__name__} to Instruction." ) from err else: raise NoiseError( f"Unacceptable Operator, not implementing to_instruction: " f"{op.__class__.__name__}") if isinstance(op, list): if all(isinstance(aop, tuple) for aop in op): num_qubits = max([max(qubits) for _, qubits in op]) + 1 circ = QuantumCircuit(num_qubits) for inst, qubits in op: try: circ.append(inst, qargs=qubits) except CircuitError as err: raise NoiseError( f"Invalid operation type: {inst.__class__.__name__}," f" not appendable to circuit.") from err return circ # Support for old-style json-like input TODO: to be removed elif all(isinstance(aop, dict) for aop in op): warnings.warn( 'Constructing QuantumError with list of dict representing a mixed channel' ' has been deprecated as of qiskit-aer 0.10.0 and will be removed' ' no earlier than 3 months from that release date.', DeprecationWarning, stacklevel=3) # Convert json-like to non-kraus Instruction num_qubits = max([max(dic['qubits']) for dic in op]) + 1 circ = QuantumCircuit(num_qubits) for dic in op: if dic['name'] == 'reset': # pylint: disable=import-outside-toplevel from qiskit.circuit import Reset circ.append(Reset(), qargs=dic['qubits']) elif dic['name'] == 'kraus': circ.append(Instruction(name='kraus', num_qubits=len(dic['qubits']), num_clbits=0, params=dic['params']), qargs=dic['qubits']) elif dic['name'] == 'unitary': circ.append(UnitaryGate(data=dic['params'][0]), qargs=dic['qubits']) else: with warnings.catch_warnings(): warnings.filterwarnings( "ignore", category=DeprecationWarning, module= "qiskit.providers.aer.noise.errors.errorutils") circ.append(UnitaryGate(label=dic['name'], data=standard_gate_unitary( dic['name'])), qargs=dic['qubits']) return circ else: raise NoiseError(f"Invalid type of op list: {op}") raise NoiseError( f"Invalid noise op type {op.__class__.__name__}: {op}")
def measure_n(num_qubits): """Multi-qubit measure instruction.""" return Instruction("measure", num_qubits, num_qubits, [])
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)