def test_standalone_and_shared_out_of_order(self): """Test circuit with register bits inserted out of order.""" qr_standalone = QuantumRegister(2, "standalone") qubits = [Qubit() for _ in range(5)] clbits = [Clbit() for _ in range(5)] qc = QuantumCircuit() qc.add_bits(qubits) qc.add_bits(clbits) random.shuffle(qubits) random.shuffle(clbits) qr = QuantumRegister(bits=qubits) cr = ClassicalRegister(bits=clbits) qc.add_register(qr) qc.add_register(cr) qr_standalone = QuantumRegister(2, "standalone") cr_standalone = ClassicalRegister(2, "classical_standalone") qc.add_bits([qr_standalone[1], qr_standalone[0]]) qc.add_bits([cr_standalone[1], cr_standalone[0]]) qc.add_register(qr_standalone) qc.add_register(cr_standalone) qc.unitary(random_unitary(32, seed=42), qr) qc.unitary(random_unitary(4, seed=100), qr_standalone) qc.measure(qr, cr) qc.measure(qr_standalone, cr_standalone) qpy_file = io.BytesIO() dump(qc, qpy_file) qpy_file.seek(0) new_circ = load(qpy_file)[0] self.assertEqual(qc, new_circ)
def test_parameter_expression(self): """Test a circuit with a parameter expression.""" theta = Parameter("theta") phi = Parameter("phi") sum_param = theta + phi qc = QuantumCircuit(5, 1) qc.h(0) for i in range(4): qc.cx(i, i + 1) qc.barrier() qc.rz(sum_param, range(3)) qc.rz(phi, 3) qc.rz(theta, 4) qc.barrier() for i in reversed(range(4)): qc.cx(i, i + 1) qc.h(0) qc.measure(0, 0) qpy_file = io.BytesIO() dump(qc, qpy_file) qpy_file.seek(0) new_circuit = load(qpy_file)[0] self.assertEqual(qc, new_circuit)
def test_initialize_qft(self): """Test that initialize with a complex statevector and qft work.""" k = 5 state = (1 / np.sqrt(8)) * np.array( [ np.exp(-1j * 2 * np.pi * k * (0) / 8), np.exp(-1j * 2 * np.pi * k * (1) / 8), np.exp(-1j * 2 * np.pi * k * (2) / 8), np.exp(-1j * 2 * np.pi * k * 3 / 8), np.exp(-1j * 2 * np.pi * k * 4 / 8), np.exp(-1j * 2 * np.pi * k * 5 / 8), np.exp(-1j * 2 * np.pi * k * 6 / 8), np.exp(-1j * 2 * np.pi * k * 7 / 8), ] ) qubits = 3 qc = QuantumCircuit(qubits, qubits) qc.initialize(state) qc.append(QFT(qubits), range(qubits)) qc.measure(range(qubits), range(qubits)) qpy_file = io.BytesIO() dump(qc, qpy_file) qpy_file.seek(0) new_circ = load(qpy_file)[0] self.assertEqual(qc, new_circ) self.assertEqual([x[0].label for x in qc.data], [x[0].label for x in new_circ.data])
def test_qpy_full_path(self): """Test full path qpy serialization for basic circuit.""" qr_a = QuantumRegister(4, "a") qr_b = QuantumRegister(4, "b") cr_c = ClassicalRegister(4, "c") cr_d = ClassicalRegister(4, "d") q_circuit = QuantumCircuit( qr_a, qr_b, cr_c, cr_d, name="MyCircuit", metadata={ "test": 1, "a": 2 }, global_phase=3.14159, ) q_circuit.h(qr_a) q_circuit.cx(qr_a, qr_b) q_circuit.barrier(qr_a) q_circuit.barrier(qr_b) q_circuit.measure(qr_a, cr_c) q_circuit.measure(qr_b, cr_d) qpy_file = io.BytesIO() dump(q_circuit, qpy_file) qpy_file.seek(0) new_circ = load(qpy_file)[0] self.assertEqual(q_circuit, new_circ) self.assertEqual(q_circuit.global_phase, new_circ.global_phase) self.assertEqual(q_circuit.metadata, new_circ.metadata) self.assertEqual(q_circuit.name, new_circ.name)
def test_string_parameter(self): """Test a PauliGate instruction that has string parameters.""" circ = (X ^ Y ^ Z).to_circuit_op().to_circuit() qpy_file = io.BytesIO() dump(circ, qpy_file) qpy_file.seek(0) new_circuit = load(qpy_file)[0] self.assertEqual(circ, new_circuit)
def test_parameter_vector_global_phase(self): """Test that a circuit with a standalone ParameterVectorElement phase works.""" vec = ParameterVector("phase", 1) qc = QuantumCircuit(1, global_phase=vec[0]) qpy_file = io.BytesIO() dump(qc, qpy_file) qpy_file.seek(0) new_circuit = load(qpy_file)[0] self.assertEqual(qc, new_circuit)
def test_circuit_with_conditional(self): """Test that instructions with conditions are correctly serialized.""" qc = QuantumCircuit(1, 1) qc.x(0).c_if(qc.cregs[0], 1) qpy_file = io.BytesIO() dump(qc, qpy_file) qpy_file.seek(0) new_circ = load(qpy_file)[0] self.assertEqual(qc, new_circ)
def test_int_parameter(self): """Test that integer parameters are correctly serialized.""" qc = QuantumCircuit(1) qc.rx(3, 0) qpy_file = io.BytesIO() dump(qc, qpy_file) qpy_file.seek(0) new_circ = load(qpy_file)[0] self.assertEqual(qc, new_circ)
def test_numpy_float_parameter(self): """Test that numpy float parameters are correctly serialized.""" qc = QuantumCircuit(1) qc.rx(np.float32(3.14), 0) qpy_file = io.BytesIO() dump(qc, qpy_file) qpy_file.seek(0) new_circ = load(qpy_file)[0] self.assertEqual(qc, new_circ)
def test_qaoa(self): """Test loading a QAOA circuit works.""" cost_operator = Z ^ I ^ I ^ Z qaoa = QAOAAnsatz(cost_operator, reps=2) qpy_file = io.BytesIO() dump(qaoa, qpy_file) qpy_file.seek(0) new_circ = load(qpy_file)[0] self.assertEqual(qaoa, new_circ) self.assertEqual([x[0].label for x in qaoa.data], [x[0].label for x in new_circ.data])
def test_nested_tuple_param(self): """Test qpy with an instruction that contains nested tuples.""" inst = Instruction("tuple_test", 1, 0, [((((0, 1), (0, 1)), 2, 3), ("A", "B", "C"))]) qc = QuantumCircuit(1) qc.append(inst, [0]) qpy_file = io.BytesIO() dump(qc, qpy_file) qpy_file.seek(0) new_circuit = load(qpy_file)[0] self.assertEqual(qc, new_circuit)
def test_unitary_gate(self): """Test that numpy array parameters are correctly serialized""" qc = QuantumCircuit(1) unitary = np.array([[0, 1], [1, 0]]) qc.unitary(unitary, 0) qpy_file = io.BytesIO() dump(qc, qpy_file) qpy_file.seek(0) new_circ = load(qpy_file)[0] self.assertEqual(qc, new_circ)
def test_opaque_instruction(self): """Test that custom opaque instruction is correctly serialized""" custom_gate = Instruction("black_box", 1, 0, []) qc = QuantumCircuit(1) qc.append(custom_gate, [0]) qpy_file = io.BytesIO() dump(qc, qpy_file) qpy_file.seek(0) new_circ = load(qpy_file)[0] self.assertEqual(qc, new_circ)
def test_empty_tuple_param(self): """Test qpy with an instruction that contains an empty tuple.""" inst = Instruction("empty_tuple_test", 1, 0, [tuple()]) qc = QuantumCircuit(1) qc.append(inst, [0]) qpy_file = io.BytesIO() dump(qc, qpy_file) qpy_file.seek(0) new_circuit = load(qpy_file)[0] self.assertEqual(qc, new_circuit)
def test_standalone_register_partial_bit_in_circuit(self): """Test qpy with only some bits from standalone register.""" qr = QuantumRegister(2) qc = QuantumCircuit([qr[0]]) qc.x(0) qpy_file = io.BytesIO() dump(qc, qpy_file) qpy_file.seek(0) new_circuit = load(qpy_file)[0] self.assertEqual(qc, new_circuit)
def test_controlled_gate(self): """Test a custom controlled gate.""" qc = QuantumCircuit(3) controlled_gate = DCXGate().control(1) qc.append(controlled_gate, [0, 1, 2]) qpy_file = io.BytesIO() dump(qc, qpy_file) qpy_file.seek(0) new_circuit = load(qpy_file)[0] self.assertEqual(qc, new_circuit)
def test_controlled_gate_open_controls(self): """Test a controlled gate with open controls round-trips exactly.""" qc = QuantumCircuit(3) controlled_gate = DCXGate().control(1, ctrl_state=0) qc.append(controlled_gate, [0, 1, 2]) qpy_file = io.BytesIO() dump(qc, qpy_file) qpy_file.seek(0) new_circuit = load(qpy_file)[0] self.assertEqual(qc, new_circuit)
def default(self, obj: Any) -> Any: # pylint: disable=arguments-differ if isinstance(obj, date): return {'__type__': 'datetime', '__value__': obj.isoformat()} if isinstance(obj, complex): return {'__type__': 'complex', '__value__': [obj.real, obj.imag]} if isinstance(obj, np.ndarray): if obj.dtype == object: return {"__type__": "ndarray", "__value__": obj.tolist()} value = _serialize_and_encode(obj, np.save, allow_pickle=False) return {'__type__': 'ndarray', '__value__': value} if isinstance(obj, set): return {'__type__': 'set', '__value__': list(obj)} if isinstance(obj, Result): return {'__type__': 'Result', '__value__': obj.to_dict()} if hasattr(obj, 'to_json'): return {'__type__': 'to_json', '__value__': obj.to_json()} if isinstance(obj, QuantumCircuit): value = _serialize_and_encode(data=obj, serializer=lambda buff, data: qpy_serialization.dump(data, buff)) return {'__type__': 'QuantumCircuit', '__value__': value} if isinstance(obj, ParameterExpression): value = _serialize_and_encode( data=obj, serializer=qpy_serialization._write_parameter_expression, compress=False, ) return {'__type__': 'ParameterExpression', '__value__': value} if isinstance(obj, Instruction): # Append instruction to empty circuit quantum_register = QuantumRegister(obj.num_qubits) quantum_circuit = QuantumCircuit(quantum_register) quantum_circuit.append(obj, quantum_register) value = _serialize_and_encode(data=quantum_circuit, serializer=lambda buff, data: qpy_serialization.dump(data, buff)) return {'__type__': 'Instruction', '__value__': value} if hasattr(obj, "settings"): return { '__type__': 'settings', '__module__': obj.__class__.__module__, '__class__': obj.__class__.__name__, '__value__': _set_int_keys_flag(copy.deepcopy(obj.settings)) } if callable(obj): warnings.warn( f"Callable {obj} is not JSON serializable and will be set to None." ) return None if HAS_SCIPY and isinstance(obj, scipy.sparse.spmatrix): value = _serialize_and_encode(obj, scipy.sparse.save_npz, compress=False) return {'__type__': 'spmatrix', '__value__': value} return super().default(obj)
def test_open_controlled_gate(self): """Test an open control is preserved across serialization.""" qc = QuantumCircuit(2) qc.cx(0, 1, ctrl_state=0) with io.BytesIO() as fd: dump(qc, fd) fd.seek(0) new_circ = load(fd)[0] self.assertEqual(qc, new_circ) self.assertEqual(qc.data[0][0].ctrl_state, new_circ.data[0][0].ctrl_state)
def test_parameter_vector_incomplete_warns(self): """Test that qpy's deserialization warns if a ParameterVector isn't fully identical.""" vec = ParameterVector("test", 3) qc = QuantumCircuit(1, name="fun") qc.rx(vec[1], 0) qpy_file = io.BytesIO() dump(qc, qpy_file) qpy_file.seek(0) with self.assertWarnsRegex(UserWarning, r"^The ParameterVector.*Elements 0, 2.*fun$"): new_circuit = load(qpy_file)[0] self.assertEqual(qc, new_circuit)
def test_unitary_gate_with_label(self): """Test that numpy array parameters are correctly serialized with a label""" qc = QuantumCircuit(1) unitary = np.array([[0, 1], [1, 0]]) unitary_gate = UnitaryGate(unitary, "My Special unitary") qc.append(unitary_gate, [0]) qpy_file = io.BytesIO() dump(qc, qpy_file) qpy_file.seek(0) new_circ = load(qpy_file)[0] self.assertEqual(qc, new_circ) self.assertEqual([x[0].label for x in qc.data], [x[0].label for x in new_circ.data])
def test_multiple_circuits(self): """Test multiple circuits can be serialized together.""" circuits = [] for i in range(10): circuits.append( random_circuit(10, 10, measure=True, conditional=True, reset=True, seed=42 + i) ) qpy_file = io.BytesIO() dump(circuits, qpy_file) qpy_file.seek(0) new_circs = load(qpy_file) self.assertEqual(circuits, new_circs)
def test_opaque_instruction_with_label(self): """Test that custom opaque instruction is correctly serialized with a label""" custom_gate = Instruction("black_box", 1, 0, []) custom_gate.label = "My Special Black Box Instruction" qc = QuantumCircuit(1) qc.append(custom_gate, [0]) qpy_file = io.BytesIO() dump(qc, qpy_file) qpy_file.seek(0) new_circ = load(qpy_file)[0] self.assertEqual(qc, new_circ) self.assertEqual([x[0].label for x in qc.data], [x[0].label for x in new_circ.data])
def test_parameter_global_phase(self): """Test a circuit with a parameter expression global_phase.""" theta = Parameter("theta") qc = QuantumCircuit(2, global_phase=theta) qc.h(0) qc.cx(0, 1) qc.measure_all() qpy_file = io.BytesIO() dump(qc, qpy_file) qpy_file.seek(0) new_circuit = load(qpy_file)[0] self.assertEqual(qc, new_circuit)
def test_circuit_with_conditional_with_label(self): """Test that instructions with conditions are correctly serialized.""" qc = QuantumCircuit(1, 1) gate = XGate(label="My conditional x gate") gate.c_if(qc.cregs[0], 1) qc.append(gate, [0]) qpy_file = io.BytesIO() dump(qc, qpy_file) qpy_file.seek(0) new_circ = load(qpy_file)[0] self.assertEqual(qc, new_circ) self.assertEqual([x[0].label for x in qc.data], [x[0].label for x in new_circ.data])
def test_standard_gate_with_label(self): """Test a standard gate with a label.""" qc = QuantumCircuit(1) gate = XGate() gate.label = "My special X gate" qc.append(gate, [0]) qpy_file = io.BytesIO() dump(qc, qpy_file) qpy_file.seek(0) new_circ = load(qpy_file)[0] self.assertEqual(qc, new_circ) self.assertEqual([x[0].label for x in qc.data], [x[0].label for x in new_circ.data])
def test_custom_metadata_serializer_full_path(self): """Test that running with custom metadata serialization works.""" class CustomObject: """Custom string container object.""" def __init__(self, string): self.string = string def __eq__(self, other): return self.string == other.string class CustomSerializer(json.JSONEncoder): """Custom json encoder to handle CustomObject.""" def default(self, o): # pylint: disable=invalid-name if isinstance(o, CustomObject): return {"__type__": "Custom", "value": o.string} return json.JSONEncoder.default(self, o) class CustomDeserializer(json.JSONDecoder): """Custom json decoder to handle CustomObject.""" def object_hook(self, o): # pylint: disable=invalid-name,method-hidden """Hook to override default decoder. Normally specified as a kwarg on load() that overloads the default decoder. Done here to avoid reimplementing the decode method. """ if "__type__" in o: obj_type = o["__type__"] if obj_type == "Custom": return CustomObject(o["value"]) return o theta = Parameter("theta") qc = QuantumCircuit(2, global_phase=theta) qc.h(0) qc.cx(0, 1) qc.measure_all() circuits = [qc, qc.copy()] circuits[0].metadata = {"key": CustomObject("Circuit 1")} circuits[1].metadata = {"key": CustomObject("Circuit 2")} qpy_file = io.BytesIO() dump(circuits, qpy_file, metadata_serializer=CustomSerializer) qpy_file.seek(0) new_circuits = load(qpy_file, metadata_deserializer=CustomDeserializer) self.assertEqual(qc, new_circuits[0]) self.assertEqual(circuits[0].metadata["key"], CustomObject("Circuit 1")) self.assertEqual(qc, new_circuits[1]) self.assertEqual(circuits[1].metadata["key"], CustomObject("Circuit 2"))
def test_qpy_with_ifelseop(self): """Test qpy serialization with an if block.""" qc = QuantumCircuit(2, 2) qc.h(0) qc.measure(0, 0) with qc.if_test((qc.clbits[0], True)): qc.x(1) qc.measure(1, 1) qpy_file = io.BytesIO() dump(qc, qpy_file) qpy_file.seek(0) new_circuit = load(qpy_file)[0] self.assertEqual(qc, new_circuit)
def test_ucr_gates(self): """Test qpy with UCRX, UCRY, and UCRZ gates.""" qc = QuantumCircuit(3) qc.ucrz([0, 0, 0, -np.pi], [0, 1], 2) qc.ucry([0, 0, 0, -np.pi], [0, 2], 1) qc.ucrx([0, 0, 0, -np.pi], [2, 1], 0) qc.measure_all() qpy_file = io.BytesIO() dump(qc, qpy_file) qpy_file.seek(0) new_circuit = load(qpy_file)[0] self.assertEqual(qc.decompose().decompose(), new_circuit.decompose().decompose())
def test_qpy_with_while_loop(self): """Test qpy serialization with a for loop.""" qc = QuantumCircuit(2, 1) with qc.while_loop((qc.clbits[0], 0)): qc.h(0) qc.cx(0, 1) qc.measure(0, 0) qpy_file = io.BytesIO() dump(qc, qpy_file) qpy_file.seek(0) new_circuit = load(qpy_file)[0] self.assertEqual(qc, new_circuit)